tor-browser

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

buffer-sizes.html (9296B)


      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>Buffer allocation test</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="canvasParent"></div>
     18 <div id="description"></div>
     19 <div id="console"></div>
     20 <script id="vshader" type="x-shader/x-vertex">
     21 attribute vec2 inPosition;
     22 attribute vec4 inColor0;
     23 attribute vec4 inColor1;
     24 attribute vec4 inColor2;
     25 attribute vec4 inColor3;
     26 attribute vec4 inColor4;
     27 attribute vec4 inColor5;
     28 attribute vec4 inColor6;
     29 attribute vec4 inColor7;
     30 
     31 varying vec4 color;
     32 
     33 void main()
     34 {
     35    color = abs(inColor0) + abs(inColor1) + abs(inColor2) + abs(inColor3) +
     36            abs(inColor4) + abs(inColor5) + abs(inColor6) + abs(inColor7);
     37 
     38    color = clamp(color, vec4(0.0), vec4(1.0));
     39 
     40    gl_Position = vec4(inPosition, 0.0, 1.0);
     41 }
     42 </script>
     43 <script id="fshader" type="x-shader/x-fragment">
     44 precision mediump float;
     45 
     46 varying vec4 color;
     47 
     48 void main()
     49 {
     50    if (color == vec4(0.0))
     51        discard;
     52 
     53    gl_FragColor = color;
     54 }
     55 </script>
     56 
     57 <script>
     58 description("Allocates a number of different sized buffers and checks that the buffers are cleared " +
     59            "OR that the allocation results in gl.OUT_OF_MEMORY or context loss.");
     60 var wtu = WebGLTestUtils;
     61 
     62 // The shader processes eight vec4 attributes at once to reduce the amount of
     63 // draw calls.
     64 var numColorAttrs = 8;
     65 
     66 // Process 64 squares at once to also reduce the amount of draw calls.
     67 var vertices = [];
     68 var w = 0.25;
     69 for (var x = -1; x < 1; x += w) {
     70    for (var y = -1; y < 1; y += w) {
     71        vertices.push(x + w, y + w);
     72        vertices.push(x,     y + w);
     73        vertices.push(x,     y    );
     74 
     75        vertices.push(x + w, y + w);
     76        vertices.push(x,     y    );
     77        vertices.push(x + w, y    );
     78    }
     79 }
     80 var numVertices = (vertices.length / 2);
     81 
     82 var gl;
     83 var squareBuffer;
     84 var error = 0;
     85 var expectContextLost = false;
     86 
     87 function initGLForBufferSizesTest() {
     88    var canvas = document.createElement("canvas");
     89    canvas.width = 40;
     90    canvas.height = 40;
     91    var parent = document.getElementById("canvasParent");
     92    parent.innerHTML = '';
     93    parent.appendChild(canvas);
     94    gl = wtu.create3DContext(canvas);
     95    var attribs = ["inPosition", "inColor0", "inColor1", "inColor2", "inColor3",
     96                   "inColor4", "inColor5", "inColor6", "inColor7"];
     97    wtu.setupProgram(gl, ["vshader", "fshader"], attribs);
     98    gl.enableVertexAttribArray(0);
     99    for (var i = 0; i < numColorAttrs; i++) {
    100        gl.enableVertexAttribArray(1 + i);
    101    }
    102    gl.disable(gl.DEPTH_TEST);
    103    gl.disable(gl.BLEND);
    104 
    105    squareBuffer = gl.createBuffer();
    106 
    107    gl.bindBuffer(gl.ARRAY_BUFFER, squareBuffer);
    108    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
    109 }
    110 
    111 function createBuffer(size, allowedToFail) {
    112    var msg = "Calling bufferData with size=" + size;
    113    var buffer = gl.createBuffer();
    114 
    115    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    116    gl.bufferData(gl.ARRAY_BUFFER, size, gl.STATIC_DRAW);
    117 
    118    error = gl.getError();
    119    if (error !== gl.NO_ERROR) {
    120        gl.deleteBuffer(buffer);
    121        if (allowedToFail) {
    122            if (error === gl.OUT_OF_MEMORY) {
    123                testPassed(msg + " failed with gl.OUT_OF_MEMORY (this is allowed)");
    124                return null;
    125            } else if (error === gl.CONTEXT_LOST_WEBGL) {
    126                testPassed(msg + " failed with gl.CONTEXT_LOST_WEBGL (this is allowed)");
    127                return null;
    128            }
    129        }
    130        testFailed(msg + " failed with error " + wtu.glEnumToString(gl, error));
    131        return null;
    132    }
    133 
    134    testPassed(msg + " did not result in any errors");
    135    var reportedSize = gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE);
    136    expectContextLost = false;
    137    if (reportedSize === null) {
    138        testPassed("Null size reported by gl, this should happen if the context is lost which is allowed.");
    139        expectContextLost = true;
    140    } else if (reportedSize !== size) {
    141        if (size > Math.pow(2, 32)) {
    142            testPassed("gl reported different size " + reportedSize + " for the buffer, but this is expected since " +
    143                       "the requested size was above what the return value of getBufferParameter can represent.");
    144        } else {
    145            testFailed("gl reported different size " + reportedSize + " for the buffer.");
    146        }
    147    } else {
    148        testPassed("Size reported by gl was the same as the requested size.");
    149    }
    150 
    151    return buffer;
    152 }
    153 
    154 // Draw a square on the canvas using attributes from the clear buffer created with bufferData.
    155 function drawWithBuffer(buffer, allowedToFail) {
    156    gl.clearColor(0, 1, 0, 1);
    157    gl.clear(gl.COLOR_BUFFER_BIT);
    158 
    159    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    160    var size = gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE);
    161    // Each vec4 is 16 bytes
    162    var increment = numVertices * numColorAttrs * 16;
    163    for (var offset = 0; offset + increment <= size; offset += increment) {
    164        gl.bindBuffer(gl.ARRAY_BUFFER, squareBuffer);
    165        gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
    166 
    167        for (var i = 0; i < numColorAttrs; i++) {
    168            gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    169            gl.vertexAttribPointer(1 + i, 4, gl.FLOAT, false, 0,
    170                                   offset + increment * i / numColorAttrs);
    171        }
    172        gl.drawArrays(gl.TRIANGLES, 0, numVertices);
    173        error = gl.getError();
    174 
    175        if (error !== gl.NO_ERROR) {
    176            if (allowedToFail) {
    177                if (error === gl.OUT_OF_MEMORY) {
    178                    testPassed("drawArrays failed with gl.OUT_OF_MEMORY (this is allowed)");
    179                    return;
    180                } else if (error === gl.CONTEXT_LOST_WEBGL) {
    181                    testPassed("drawArrays failed with gl.CONTEXT_LOST_WEBGL (this is allowed)");
    182                    return;
    183                }
    184            }
    185            testFailed("drawArrays failed with error " + wtu.glEnumToString(gl, error));
    186            return;
    187        }
    188    }
    189    wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
    190 }
    191 
    192 
    193 // To be able to confirm the whole buffer has been cleared, the size needs to
    194 // be divisible by the amount of vertices. Thus most sizes are multiples of 3.
    195 var tests = [
    196    // Reasonable sized buffers.
    197    { size: 3 * 1024,              allowedToFail: false, tryDrawing: true },
    198    { size: 3 * 1024 * 1024,       allowedToFail: false, tryDrawing: true },
    199    { size: 3 * 1024 * 1024 * 16,  allowedToFail: false, tryDrawing: true },
    200 
    201    // Huge buffers, which are meant to test out of memory handling.
    202    // Allowed failures are gl.OUT_OF_MEMORY or context loss.
    203    // Succeeding in the allocations is allowed as well for forward compatibility.
    204 
    205    // 1.5 GB allocation for stressing lower-end 32-bit systems.
    206    // Allocation is likely to succeed on higher-end hardware.
    207    { size: 3 * 1024 * 1024 * 512, allowedToFail: true,  tryDrawing: true },
    208    // A buffer that no implementation will be able to allocate for some time
    209    // to come. To do this, we use half of the lower 43-bit half of a 44-bit
    210    // memory address space, so that the size is still valid on current common
    211    // 64-bit implementations, and also below 52-bit limit for exact conversion
    212    // from float to long long in WebIDL (though 2^n should be safe anyway).
    213    // The 4 TB size is large enough that even extrapolating the historical
    214    // exponential growth trend of memory sizes, hardware in 2020's should
    215    // still have some trouble actually doing the allocation.
    216    { size: (1 << 12) * (1 << 30), allowedToFail: true,  tryDrawing: false }
    217 ];
    218 
    219 function finishBufferSizesTest() {
    220    gl.deleteBuffer(squareBuffer);
    221    finishTest();
    222 }
    223 
    224 var testIndex = -1;
    225 function runNextTest() {
    226    ++testIndex;
    227    if (testIndex > 0 && tests[testIndex - 1].allowedToFail) {
    228        if (gl.isContextLost() || error === gl.OUT_OF_MEMORY) {
    229            initGLForBufferSizesTest();
    230        } else if (expectContextLost) {
    231            testFailed("Context was not lost after timeout even though gl.getBufferParameter returned null.");
    232        }
    233    }
    234    var buffer = createBuffer(tests[testIndex].size, tests[testIndex].allowedToFail);
    235    if (buffer) {
    236        if (tests[testIndex].tryDrawing) {
    237            drawWithBuffer(buffer, tests[testIndex].allowedToFail);
    238        }
    239        gl.deleteBuffer(buffer);
    240    }
    241 
    242    if (testIndex + 1 >= tests.length) {
    243        finishBufferSizesTest();
    244    } else {
    245        if (tests[testIndex + 1].allowedToFail && !tests[testIndex].allowedToFail) {
    246            if (!confirm("The following tests can cause unresponsiveness or instability. Press OK to continue.")) {
    247                testFailed("Tests aborted");
    248                return;
    249            }
    250        }
    251        if (tests[testIndex].allowedToFail) {
    252            // Give plenty of time for possible context loss
    253            setTimeout(runNextTest(), 5000);
    254        } else {
    255            runNextTest();
    256        }
    257    }
    258 };
    259 
    260 initGLForBufferSizesTest();
    261 runNextTest();
    262 
    263 var successfullyParsed = true;
    264 </script>
    265 
    266 </body>
    267 </html>