tor-browser

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

index.html (14340B)


      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 lang="en">
      9 <head>
     10    <meta charset="utf-8">
     11    <title>Parallel Shader Compile test</title>
     12 
     13    <style>
     14        body {
     15            margin: 0;
     16        }
     17        #log {
     18            margin: 16px;
     19        }
     20        @keyframes move {
     21            0% { left: 0%; }
     22            50% { left: calc(100% - 64px); }
     23            100% { left: 0%; }
     24        }
     25        #block {
     26            position: relative;
     27            bottom: 0%;
     28            left: 0%;
     29            width: 32px;
     30            height: 32px;
     31            background-color: #07f;
     32 
     33            animation-name: move;
     34            animation-duration: 2000ms;
     35            animation-iteration-count: infinite;
     36        }
     37        .container {
     38            display: flex;
     39            flex-wrap: wrap;
     40        }
     41        .button {
     42            width: 260px
     43        }
     44    </style>
     45 </head>
     46 <body>
     47    <pre id='log'></pre>
     48 
     49    <!-- The smoothness of the block's moving indicates whether the main thread is too busy. -->
     50    <div id='block'></div>
     51 
     52    <script>
     53        var testGroup;
     54 
     55        window.addEventListener('error', function (err) {
     56            var logElement = document.getElementById('log');
     57            logElement.textContent += ' \n';
     58            logElement.textContent += err.error.stack.replace(
     59                new RegExp(window.location.href, 'g'), '/') + '\n';
     60        });
     61 
     62        function setupGLContextSerial(testRun) {
     63            var infoElement = testRun.logElement;
     64 
     65            testRun.gl = document.createElement('canvas').getContext('webgl2');
     66            if (testRun.gl) {
     67                infoElement.textContent += 'webgl2 context created.' + '\n\n';
     68                return true;
     69            } else {
     70                infoElement.textContent += 'webgl2 context is not supported.' + '\n\n';
     71                return false;
     72            }
     73        }
     74 
     75        function setupGLContextParallel(testRun) {
     76            var infoElement = testRun.logElement;
     77            if (setupGLContextSerial(testRun)) {
     78                // Enable KHR_parallel_shader_compile extension
     79                testRun.ext = testRun.gl.getExtension('KHR_parallel_shader_compile');
     80                if (testRun.ext) {
     81                    return true;
     82                } else {
     83                    infoElement.textContent += 'KHR_parallel_shader_compile is unavailable, you' +
     84                        ' may need to turn on the webgl draft extensions for your browser.'
     85                }
     86            }
     87            return false;
     88        }
     89 
     90        function releasePrograms(testRun) {
     91            var gl = testRun.gl;
     92 
     93            var programs = testRun.programs;
     94            for (var i = 0; i < programs.length; i++) {
     95                var program = programs[i];
     96                if (program.vShader) {
     97                    gl.deleteShader(program.vShader);
     98                    program.vShader = null;
     99                }
    100                if (program.fShader) {
    101                    gl.deleteShader(program.fShader);
    102                    program.fShader = null;
    103                }
    104                if (program.program) {
    105                    gl.deleteProgram(program.program);
    106                    program.program = null;
    107                }
    108            }
    109        }
    110 
    111        function showStatistics(testRun) {
    112            var infoElement = testRun.logElement;
    113            infoElement.textContent += ' ' + '\n';
    114            infoElement.textContent += (Math.round(testRun.elapsedTotal * 100) / 100) +
    115                'ms - ' + 'all shaders compiled, and linked.\n';
    116            infoElement.textContent += ' ' + '\n';
    117            infoElement.textContent += 'done.' + '\n';
    118 
    119            releasePrograms(testRun);
    120        }
    121 
    122        function checkShader(gl, shader, infoElement) {
    123            if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
    124                var info = gl.getShaderInfoLog(shader);
    125                infoElement.textContent += 'couldn\'t compile shader:\n';
    126                infoElement.textContent += info.toString() + '\n';
    127                return false;
    128            }
    129            return true;
    130        }
    131 
    132        function checkProgram(gl, program, infoElement) {
    133            if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
    134                var info = gl.getProgramInfoLog(program);
    135                infoElement.textContent += ' ' + '\n';
    136                infoElement.textContent += 'couldn\'t link program:\n';
    137                infoElement.textContent += info.toString() + '\n';
    138                return false;
    139            }
    140            return true;
    141         }
    142 
    143        function makeAllProgramsSerial(testRun) {
    144            var gl = testRun.gl;
    145            var infoElement = testRun.logElement;
    146 
    147            var programs = testRun.programs;
    148            for (var i = 0; i < programs.length; i++) {
    149                var program = programs[i];
    150                // vertex shader compilation
    151                var vShader = gl.createShader(gl.VERTEX_SHADER);
    152                gl.shaderSource(vShader, program.vSource);
    153                gl.compileShader(vShader);
    154                checkShader(gl, vShader, infoElement);
    155 
    156                // fragment shader compilation
    157                var fShader = gl.createShader(gl.FRAGMENT_SHADER);
    158                gl.shaderSource(fShader, program.fSource);
    159                gl.compileShader(fShader);
    160                checkShader(gl, fShader, infoElement);
    161 
    162                // program
    163                var programHandle = gl.createProgram();
    164                gl.attachShader(programHandle, vShader);
    165                gl.attachShader(programHandle, fShader);
    166                gl.linkProgram(programHandle);
    167                checkProgram(gl, programHandle, infoElement);
    168            }
    169            testRun.elapsedTotal = performance.now() - testRun.start;
    170            showStatistics(testRun);
    171        };
    172 
    173        function makeAllProgramsParallel(testRun) {
    174            var gl = testRun.gl;
    175            var infoElement = testRun.logElement;
    176 
    177            var programs = testRun.programs;
    178            for (var i = 0; i < programs.length; i++) {
    179                var program = programs[i];
    180                var vShader = gl.createShader(gl.VERTEX_SHADER);
    181                gl.shaderSource(vShader, program.vSource);
    182                gl.compileShader(vShader);
    183 
    184                var fShader = gl.createShader(gl.FRAGMENT_SHADER);
    185                gl.shaderSource(fShader, program.fSource);
    186                gl.compileShader(fShader);
    187 
    188                programHandle = gl.createProgram();
    189                gl.attachShader(programHandle, vShader);
    190                gl.attachShader(programHandle, fShader);
    191 
    192                program.vShader = vShader;
    193                program.fShader = fShader;
    194                program.program = programHandle;
    195                program.status = "Compiling";
    196            }
    197 
    198            function checkCompletion() {
    199                var ext = testRun.ext;
    200 
    201                var allProgramsLinked = true;
    202 
    203                for (var i = 0; i < programs.length; i++) {
    204                    var program = programs[i];
    205                    switch (program.status) {
    206                        case "Compiling":
    207                            if (gl.getShaderParameter(program.vShader, ext.COMPLETION_STATUS_KHR) &&
    208                                gl.getShaderParameter(program.fShader, ext.COMPLETION_STATUS_KHR))
    209                            {
    210                                checkShader(gl, program.vShader, infoElement);
    211                                checkShader(gl, program.fShader, infoElement);
    212                                gl.linkProgram(program.program);
    213                                program.status = "Linking";
    214                            }
    215                            allProgramsLinked = false;
    216                            break;
    217 
    218                        case "Linking":
    219                            if (gl.getProgramParameter(program.program, ext.COMPLETION_STATUS_KHR))
    220                            {
    221                                checkProgram(gl, program.program, infoElement);
    222                                program.status = "Done";
    223                            }
    224                            else {
    225                                allProgramsLinked = false;
    226                            }
    227                            break;
    228 
    229                        case "Done":
    230                            break;
    231                    }
    232                }
    233 
    234                if (allProgramsLinked) {
    235                    testRun.elapsedTotal = performance.now() - testRun.start;
    236                    showStatistics(testRun);
    237                }
    238                else {
    239                    requestAnimationFrame(checkCompletion);
    240                }
    241            }
    242            requestAnimationFrame(checkCompletion);
    243        }
    244 
    245        function parsePrograms(testRun) {
    246            var gl = testRun.gl;
    247            var infoElement = testRun.logElement;
    248 
    249            // Parse programs from the cached text, formatted as:
    250            //    __BEGINPROGRAM__
    251            //    __VERTEXSHADER__
    252            //        shader source line
    253            //        ...
    254            //    __FRAGMENTSHADER__
    255            //        shader source line
    256            //        ...
    257            //    __ENDPROGRAM__
    258            //
    259            //    __BEGINPROGRAM__
    260            //    ...
    261            var arrayOfLines = testRun.test.shaderCache.match(/[^\r\n]+/g);
    262            var programs = [];
    263            var currentProgram = {};
    264            var currentShader;
    265            var shaderSourceLine = false;
    266            for (var ii = 0; ii < arrayOfLines.length; ii++) {
    267                var cur = arrayOfLines[ii];
    268                // Use random numbers to fool the program cache mechanism.
    269                if (cur.indexOf('PROGRAM_CACHE_BREAKER_RANDOM') != -1) {
    270                    cur = cur.replace('PROGRAM_CACHE_BREAKER_RANDOM', Math.random())
    271                }
    272 
    273                if (cur == '__VERTEXSHADER__') {
    274                    currentShader = [];
    275                    shaderSourceLine = true;
    276                } else if (cur == '__FRAGMENTSHADER__') {
    277                    currentProgram.vSource = currentShader.join('\n');
    278 
    279                    currentShader = [];
    280                    shaderSourceLine = true;
    281                } else if (cur == '__ENDPROGRAM__') {
    282                    currentProgram.fSource = currentShader.join('\n');
    283                    programs.push(currentProgram);
    284 
    285                    currentProgram = {};
    286                    currentShader = [];
    287                    shaderSourceLine = false;
    288                } else if (shaderSourceLine) {
    289                    currentShader.push(cur);
    290                }
    291            }
    292 
    293            infoElement.textContent += programs.length + ' programs found.' + '\n';
    294            infoElement.textContent += 'starting compilations ...' + '\n';
    295 
    296            testRun.start = performance.now();
    297 
    298            testRun.programs = programs;
    299 
    300            testRun.makeAllPrograms(testRun);
    301        };
    302 
    303 
    304        function runTest(index, isParallel) {
    305            var testRun = {};
    306            var test = testGroup[index];
    307            testRun.test = test;
    308            testRun.name = test.name + (isParallel ? "_parallel" : "_serial");
    309            testRun.logElement = document.getElementById(testRun.name);
    310            testRun.logElement.textContent = '';
    311 
    312            testRun.setupGLContext =
    313                (isParallel ? setupGLContextParallel : setupGLContextSerial);
    314 
    315            testRun.makeAllPrograms =
    316                (isParallel ? makeAllProgramsParallel : makeAllProgramsSerial);
    317 
    318            if (!testRun.setupGLContext(testRun)) {
    319                return;
    320            }
    321 
    322            if (test.shaderCache === undefined) {
    323                // load shader cache
    324                var xhr = new XMLHttpRequest();
    325                xhr.addEventListener('load', function() {
    326                    test.shaderCache = xhr.responseText;
    327 
    328                    requestAnimationFrame(function() {
    329                        parsePrograms(testRun);
    330                    });
    331                });
    332                xhr.open('GET', test.location);
    333                xhr.send();
    334            } else {
    335                parsePrograms(testRun);
    336            }
    337        }
    338 
    339        function createElement(element, attribute, inner) {
    340            if (element === undefined) {
    341                return false;
    342            }
    343            if (inner === undefined) {
    344                inner = [];
    345            }
    346            var el = document.createElement(element);
    347            if (typeof(attribute) === 'object') {
    348                for (var key in attribute) {
    349                    el.setAttribute(key, attribute[key]);
    350                }
    351            }
    352            if (!Array.isArray(inner)) {
    353                inner = [inner];
    354            }
    355            for (var k = 0; k < inner.length; k++) {
    356                if (inner[k].tagName) {
    357                    el.appendChild(inner[k]);
    358                } else {
    359                    el.appendChild(document.createTextNode(inner[k]));
    360                }
    361            }
    362            return el;
    363        }
    364 
    365        var container = createElement("div", {"class": "container"});
    366        document.body.appendChild(container);
    367 
    368        testGroup = [{
    369            'location': './shaders/aquarium/shader-cache.txt',
    370            'name': 'aquarium'
    371            },
    372        ];
    373 
    374        testGroup.forEach((test, index) => {
    375 
    376            function createTestView(test, index, isParallel) {
    377 
    378                testName = test.name + (isParallel ? "_parallel" : "_serial");
    379 
    380                var tButton = createElement(
    381                    'button',
    382                    {'class': 'button', 'onclick': 'runTest(' + index + ', ' + isParallel + ')'},
    383                    testName
    384                );
    385 
    386                var tPrex = createElement("pre");
    387                var tPre = createElement("textarea", { "id": testName, "rows": 10, "cols": 30});
    388                var tDivContainer = createElement(
    389                    "div",
    390                    {"id": " " + testName + "_container"},
    391                    [tButton, tPrex, tPre]
    392                );
    393                container.appendChild(tDivContainer);
    394            }
    395 
    396            createTestView(test, index, false);
    397            createTestView(test, index, true);
    398        });
    399 
    400    </script>
    401 </body>