tor-browser

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

integer-cubemap-specification-order-bug.html (9638B)


      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 Integer Cubemap Texture Specification Order Bug 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 <canvas id="example" width="128" height="128"></canvas>
     18 <div id="description"></div>
     19 <div id="console"></div>
     20 <script id="vs" type="x-shader/x-vertex">#version 300 es
     21  precision highp float;
     22  in vec4 a_position;
     23  void main(){
     24      gl_Position = a_position;
     25  }
     26 </script>
     27 <script id="fs" type="x-shader/x-fragment">#version 300 es
     28  precision highp float;
     29  // This program samples both textures at varying Lod and exposes
     30  // both of them, the regular on top, and the weird on the bottom.
     31  // On the NVIDIA driver the top is both green and red while the bottom
     32  // is only green. This is a driver bug because both textures should be
     33  // exactly the same.
     34  // I think that because of our level specification order weirdness, the
     35  // driver gets confused as to which levels are complete and thinks only
     36  // level 0 is complete. Then when sampling the texture it clamps the sampling
     37  // to only level 0, resulting in green for all Lod values.
     38  layout(location = 0) out vec4 fragColor;
     39  uniform highp isamplerCube texRegular;
     40  uniform highp isamplerCube texWeird;
     41  void main() {
     42      vec2 fragPos = gl_FragCoord.xy / vec2(128.0, 128.0);
     43      float lod = (fragPos.x - 0.5) * 10.0 + 0.5;
     44 
     45      ivec4 colorRegular = textureLod(texRegular, vec3(1.0, 0.0, 0.0), lod);
     46      ivec4 colorWeird = textureLod(texWeird, vec3(1.0, 0.0, 0.0), lod);
     47 
     48      if (fragPos.y > 0.51) {
     49          fragColor = vec4(vec2(colorRegular.rg), 0.0, 1.0);
     50      } else if (fragPos.y < 0.49){
     51          fragColor = vec4(vec2(colorWeird.rg), 0.0, 1.0);
     52      } else {
     53          fragColor = vec4(0.0, 0.0, 0.0, 1.0);
     54      }
     55  }
     56 </script>
     57 <script>
     58 "use strict";
     59 
     60 var wtu = WebGLTestUtils;
     61 
     62 description("Test for a driver bug when specifying integer cubemaps in weird order");
     63 
     64 var gl = wtu.create3DContext("example", undefined, 2);
     65 
     66 function createTextureCube(layers, maxLevel) {
     67    var texture = gl.createTexture();
     68    gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
     69 
     70    layers.forEach(function(layer) {
     71        var level = layer.level;
     72        var face = layer.face;
     73        var color = layer.color;
     74 
     75        var levelSize = 1 << (maxLevel - level);
     76 
     77        var backingBuffer = new ArrayBuffer(levelSize * levelSize * 2);
     78        new Int16Array(backingBuffer).fill(color);
     79        gl.texImage2D(face + gl.TEXTURE_CUBE_MAP_POSITIVE_X, level, gl.RG8I, levelSize, levelSize, 0, gl.RG_INTEGER, gl.BYTE, new Int8Array(backingBuffer));
     80    });
     81 
     82    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST);
     83    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
     84    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
     85    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
     86 
     87    return texture;
     88 }
     89 
     90 function makePermutedLayers(layers, permutation) {
     91    return permutation.map(i => layers[i]);
     92 }
     93 
     94 function test() {
     95    var kMaxLevel = 4;
     96    var kBlack = 0x0000;
     97    var kGreen = 0x7F00;
     98    var kRed = 0x007F;
     99 
    100    // Create two integer cubemaps with green on level 0 and red on the others.
    101 
    102    // The "regular" cube map is filled in a sensible manner.
    103    var regularLayers = [];
    104    for (var level = 0; level <= kMaxLevel; level ++) {
    105        for (var face = 0; face < 6; face ++) {
    106            if (level == 0) {
    107                regularLayers.push({level: level, face: face, color: kGreen});
    108            } else {
    109                regularLayers.push({level: level, face: face, color: kRed});
    110            }
    111        }
    112    }
    113 
    114    // The "weird" cube map has all its >= 1 levels filled, then the first level,
    115    // then the >= 1 levels again but for one face. This replicates what the
    116    // Chromium command buffer "cubemap completeness" workaround is doing.
    117    var weirdLayers = [];
    118    for (var level = 1; level <= kMaxLevel; level ++) {
    119        for (var face = 0; face < 5; face ++) {
    120            weirdLayers.push({level: level, face: face, color: kBlack});
    121        }
    122        weirdLayers.push({level: level, face: 5, color: kRed});
    123    }
    124    for (var level = 0; level <= kMaxLevel; level ++) {
    125        for (var face = 0; face < 6; face ++) {
    126            if (level == 0) {
    127                weirdLayers.push({level: level, face: face, color: kGreen});
    128            } else {
    129                if (face != 5) {
    130                    weirdLayers.push({level: level, face: face, color: kRed});
    131                }
    132            }
    133        }
    134    }
    135 
    136    var regularTex = createTextureCube(regularLayers, kMaxLevel);
    137 
    138    var sampleProgram = wtu.setupProgram(gl, ["vs", "fs"], ["a_position"]);
    139    var regularLocation = gl.getUniformLocation(sampleProgram, "texRegular");
    140    var weirdLocation = gl.getUniformLocation(sampleProgram, "texWeird");
    141 
    142    wtu.setupQuad(gl, gl.getAttribLocation(sampleProgram, "a_position"));
    143 
    144    gl.uniform1i(regularLocation, 0);
    145    gl.uniform1i(weirdLocation, 1);
    146 
    147    function testcase(layers1, casename) {
    148        var tex1 = createTextureCube(layers1, kMaxLevel);
    149 
    150        gl.activeTexture(gl.TEXTURE0);
    151        gl.bindTexture(gl.TEXTURE_CUBE_MAP, regularTex);
    152        gl.activeTexture(gl.TEXTURE1);
    153        gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex1);
    154        // At this point both textures should be the same.
    155        wtu.drawUnitQuad(gl);
    156 
    157        gl.deleteTexture(tex1);
    158 
    159        wtu.checkCanvasRect(gl, 96, 32, 1, 1, [255, 0, 0, 255], "should be green: " + casename);
    160        wtu.checkCanvasRect(gl, 96, 96, 1, 1, [255, 0, 0, 255], "should be green: " + casename);
    161        wtu.checkCanvasRect(gl, 32, 32, 1, 1, [0, 255, 0, 255], "should be red: " + casename);
    162        wtu.checkCanvasRect(gl, 32, 96, 1, 1, [0, 255, 0, 255], "should be red: " + casename);
    163    }
    164 
    165    testcase(weirdLayers, "original");
    166    const cases = [
    167        [10,23,3,19,26,29,14,9,4,11,27,28,13,24,20,12,17,21,16,5,6,25,1,15,22,8,7,18,0,2],
    168        [10,27,3,29,17,28,13,20,18,25,9,2,8,4,24,12,15,7,19,11,6,14,16,21,1,26,23,22,0,5],
    169        [11,4,15,13,26,24,25,2,19,20,16,23,1,18,28,27,6,21,14,8,17,29,3,10,12,9,22,7,0,5],
    170        [14,2,6,28,7,25,11,26,22,13,19,21,24,4,16,29,9,27,3,17,18,15,12,20,8,23,10,1,0,5],
    171        [14,20,22,16,11,27,17,21,15,3,5,28,6,2,9,12,7,24,1,26,8,19,23,25,18,13,29,10,0,4],
    172        [14,20,22,16,11,27,17,21,15,3,5,28,6,2,9,12,7,24,1,26,8,19,23,25,18,13,29,10,0,4],
    173        [14,22,27,1,12,24,13,21,6,10,20,28,23,16,5,18,7,3,25,2,11,19,17,26,8,29,15,9,0,4],
    174        [15,22,13,28,6,12,19,9,18,11,3,23,17,8,10,20,5,14,4,25,27,26,21,16,29,24,7,0,1,2],
    175        [15,22,13,28,6,12,19,9,18,11,3,23,17,8,10,20,5,14,4,25,27,26,21,16,29,24,7,0,1,2],
    176        [16,22,18,15,19,6,21,27,4,14,29,17,7,9,11,20,24,23,28,25,2,13,10,26,8,12,3,0,5,1],
    177        [16,26,18,7,20,25,11,24,2,1,28,13,29,10,27,21,6,15,5,19,17,12,14,9,23,22,8,3,0,4],
    178        [2,22,25,12,19,16,7,27,9,10,8,17,18,24,1,21,20,14,13,4,11,29,15,5,23,26,6,28,0,3],
    179        [2,9,16,26,6,15,4,3,17,13,21,10,7,22,23,29,19,18,12,24,14,25,8,5,20,28,11,27,0,1],
    180        [2,9,16,26,6,15,4,3,17,13,21,10,7,22,23,29,19,18,12,24,14,25,8,5,20,28,11,27,0,1],
    181        [20,21,24,15,5,13,6,12,2,17,10,14,27,16,8,22,9,25,29,1,28,11,4,19,7,23,26,18,0,3],
    182        [21,14,19,12,28,6,10,7,16,27,11,22,20,24,25,26,3,8,4,18,5,2,9,15,17,23,13,29,0,1],
    183        [22,4,18,7,11,6,23,17,14,3,13,21,15,19,25,28,9,8,10,12,29,16,27,2,24,1,20,26,0,5],
    184        [22,4,18,7,11,6,23,17,14,3,13,21,15,19,25,28,9,8,10,12,29,16,27,2,24,1,20,26,0,5],
    185        [23,21,9,28,22,15,25,12,24,18,29,2,17,1,14,4,16,26,3,11,27,13,8,7,6,20,10,19,0,5],
    186        [23,6,15,13,19,2,12,7,11,29,3,20,17,10,4,18,1,22,16,27,24,9,21,25,14,26,8,28,0,5],
    187        [25,12,1,4,9,22,16,28,6,11,14,29,15,2,5,13,10,20,21,19,23,27,18,26,7,8,17,24,0,3],
    188        [25,13,29,26,28,17,19,23,7,24,10,1,15,8,3,11,18,21,27,22,12,5,9,6,16,14,20,2,0,4],
    189        [25,18,28,12,27,13,11,4,29,8,21,15,9,6,26,20,22,23,24,17,5,16,2,7,14,19,10,0,1,3],
    190        [25,19,3,10,23,15,27,18,12,8,7,24,16,14,26,4,21,5,9,1,22,28,20,29,6,11,13,17,0,2],
    191        [25,24,12,9,13,10,23,4,19,29,16,1,15,8,21,26,18,11,17,7,20,28,22,14,27,6,0,2,5,3],
    192        [25,9,29,8,3,6,10,27,11,28,13,23,18,16,17,19,5,22,12,26,21,4,7,14,24,15,2,20,0,1],
    193        [27,23,20,2,12,14,6,19,3,28,18,10,29,11,13,22,21,7,15,9,8,17,25,16,26,24,4,5,0,1],
    194        [27,7,2,5,19,10,3,26,22,18,23,16,9,24,21,17,6,28,12,14,25,29,13,15,8,20,11,4,0,1],
    195        [28,7,10,9,29,27,2,20,1,26,11,5,12,23,25,3,17,16,24,13,8,6,14,18,21,19,15,22,0,4],
    196        [28,8,23,13,18,29,20,9,10,27,15,21,3,19,14,4,26,5,24,1,6,17,11,12,16,7,25,22,0,2],
    197        [29,12,13,2,22,19,16,7,14,11,24,23,28,15,17,9,20,21,18,26,27,25,10,5,8,6,4,3,0,1],
    198        [29,8,5,4,7,15,19,17,3,26,13,9,23,6,25,22,27,24,14,16,10,21,11,18,28,12,2,20,0,1],
    199        [5,18,6,17,19,16,13,11,28,8,10,4,29,26,20,24,9,7,21,25,27,23,22,2,15,14,12,0,3,1],
    200        [5,23,2,15,7,13,19,11,27,3,22,14,4,26,28,20,17,18,8,25,16,29,10,24,12,9,6,21,0,1],
    201        [7,24,27,26,16,18,22,20,10,11,9,19,23,12,17,13,4,2,6,1,21,25,15,28,8,3,29,14,0,5],
    202    ];
    203    for (const c of cases) {
    204        testcase(makePermutedLayers(regularLayers, c), "case " + c.toString());
    205    }
    206 }
    207 
    208 test();
    209 
    210 debug("");
    211 var successfullyParsed = true;
    212 </script>
    213 <script src="../../../js/js-test-post.js"></script>
    214 
    215 </body>
    216 </html>