tor-browser

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

shader-precision-format.html (11756B)


      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 <!DOCTYPE html>
      7 <html>
      8 <head>
      9 <meta charset="utf-8">
     10 <title>WebGL shader precision format test.</title>
     11 <link rel="stylesheet" href="../../resources/js-test-style.css"/>
     12 <script src="../../js/js-test-pre.js"></script>
     13 <script src="../../js/webgl-test-utils.js"> </script>
     14 </head>
     15 <body>
     16 <canvas id="canvas" width="2" height="2" style="width: 40px; height: 40px;"></canvas>
     17 <div id="description"></div>
     18 <div id="console"></div>
     19 <script>
     20 "use strict";
     21 var wtu = WebGLTestUtils;
     22 description(document.title);
     23 debug("Tests that WebGLShaderPrecisionFormat class and getShaderPrecisionFormat work.");
     24 debug("");
     25 var gl = wtu.create3DContext("canvas");
     26 
     27 function verifyShaderPrecisionFormat(shadertype, precisiontype) {
     28    shouldBeTrue('gl.getShaderPrecisionFormat(' + shadertype + ', ' +
     29                 precisiontype + ') instanceof WebGLShaderPrecisionFormat');
     30 }
     31 
     32 debug("");
     33 debug("Test that getShaderPrecisionFormat returns a WebGLShaderPrecisionFormat object.");
     34 debug("");
     35 
     36 verifyShaderPrecisionFormat('gl.VERTEX_SHADER', 'gl.LOW_FLOAT');
     37 verifyShaderPrecisionFormat('gl.VERTEX_SHADER', 'gl.MEDIUM_FLOAT');
     38 verifyShaderPrecisionFormat('gl.VERTEX_SHADER', 'gl.HIGH_FLOAT');
     39 verifyShaderPrecisionFormat('gl.VERTEX_SHADER', 'gl.LOW_INT');
     40 verifyShaderPrecisionFormat('gl.VERTEX_SHADER', 'gl.MEDIUM_INT');
     41 verifyShaderPrecisionFormat('gl.VERTEX_SHADER', 'gl.HIGH_INT');
     42 verifyShaderPrecisionFormat('gl.FRAGMENT_SHADER', 'gl.LOW_FLOAT');
     43 verifyShaderPrecisionFormat('gl.FRAGMENT_SHADER', 'gl.MEDIUM_FLOAT');
     44 verifyShaderPrecisionFormat('gl.FRAGMENT_SHADER', 'gl.HIGH_FLOAT');
     45 verifyShaderPrecisionFormat('gl.FRAGMENT_SHADER', 'gl.LOW_INT');
     46 verifyShaderPrecisionFormat('gl.FRAGMENT_SHADER', 'gl.MEDIUM_INT');
     47 verifyShaderPrecisionFormat('gl.FRAGMENT_SHADER', 'gl.HIGH_INT');
     48 
     49 debug("");
     50 debug("Test that getShaderPrecisionFormat throws an error with invalid parameters.");
     51 debug("");
     52 
     53 wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, 'gl.getShaderPrecisionFormat(gl.HIGH_INT, gl.VERTEX_SHADER)');
     54 
     55 debug("");
     56 debug("Test that WebGLShaderPrecisionFormat values are sensible.");
     57 debug("");
     58 
     59 // The minimum values are from OpenGL ES Shading Language spec, section 4.5.
     60 
     61 var shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.LOW_FLOAT);
     62 shouldBeTrue('shaderPrecisionFormat.rangeMin >= 1');
     63 shouldBeTrue('shaderPrecisionFormat.rangeMax >= 1');
     64 shouldBeTrue('shaderPrecisionFormat.precision >= 8');
     65 
     66 shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.MEDIUM_FLOAT);
     67 shouldBeTrue('shaderPrecisionFormat.rangeMin >= 14');
     68 shouldBeTrue('shaderPrecisionFormat.rangeMax >= 14');
     69 shouldBeTrue('shaderPrecisionFormat.precision >= 10');
     70 
     71 shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_FLOAT);
     72 shouldBeTrue('shaderPrecisionFormat.rangeMin >= 62');
     73 shouldBeTrue('shaderPrecisionFormat.rangeMax >= 62');
     74 shouldBeTrue('shaderPrecisionFormat.precision >= 16');
     75 
     76 shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.LOW_INT);
     77 shouldBeTrue('shaderPrecisionFormat.rangeMin >= 8');
     78 shouldBeTrue('shaderPrecisionFormat.rangeMax >= 8');
     79 shouldBeTrue('shaderPrecisionFormat.precision == 0');
     80 
     81 shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.MEDIUM_INT);
     82 shouldBeTrue('shaderPrecisionFormat.rangeMin >= 10');
     83 shouldBeTrue('shaderPrecisionFormat.rangeMax >= 10');
     84 shouldBeTrue('shaderPrecisionFormat.precision == 0');
     85 
     86 shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_INT);
     87 shouldBeTrue('shaderPrecisionFormat.rangeMin >= 16');
     88 shouldBeTrue('shaderPrecisionFormat.rangeMax >= 16');
     89 shouldBeTrue('shaderPrecisionFormat.precision == 0');
     90 
     91 var shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.LOW_FLOAT);
     92 shouldBeTrue('shaderPrecisionFormat.rangeMin >= 1');
     93 shouldBeTrue('shaderPrecisionFormat.rangeMax >= 1');
     94 shouldBeTrue('shaderPrecisionFormat.precision >= 8');
     95 
     96 shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT);
     97 shouldBeTrue('shaderPrecisionFormat.rangeMin >= 14');
     98 shouldBeTrue('shaderPrecisionFormat.rangeMax >= 14');
     99 shouldBeTrue('shaderPrecisionFormat.precision >= 10');
    100 
    101 shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.LOW_INT);
    102 shouldBeTrue('shaderPrecisionFormat.rangeMin >= 8');
    103 shouldBeTrue('shaderPrecisionFormat.rangeMax >= 8');
    104 shouldBeTrue('shaderPrecisionFormat.precision == 0');
    105 
    106 shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_INT);
    107 shouldBeTrue('shaderPrecisionFormat.rangeMin >= 10');
    108 shouldBeTrue('shaderPrecisionFormat.rangeMax >= 10');
    109 shouldBeTrue('shaderPrecisionFormat.precision == 0');
    110 
    111 debug("");
    112 debug("Test optional highp support in fragment shaders.");
    113 debug("");
    114 
    115 shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT);
    116 shouldBeTrue('(shaderPrecisionFormat.rangeMin == 0 && shaderPrecisionFormat.rangeMax == 0 && shaderPrecisionFormat.precision == 0) || (shaderPrecisionFormat.rangeMin >= 62 && shaderPrecisionFormat.rangeMax >= 62 && shaderPrecisionFormat.precision >= 16)');
    117 
    118 shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_INT);
    119 shouldBeTrue('(shaderPrecisionFormat.rangeMin == 0 && shaderPrecisionFormat.rangeMax == 0 && shaderPrecisionFormat.precision == 0) || (shaderPrecisionFormat.rangeMin >= 16 && shaderPrecisionFormat.rangeMax >= 16 && shaderPrecisionFormat.precision == 0)');
    120 
    121 debug("");
    122 debug("Test that getShaderPrecisionFormat returns the same thing every call.");
    123 debug("");
    124 
    125 shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.LOW_FLOAT);
    126 var shaderPrecisionFormat2 = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.LOW_FLOAT);
    127 shouldBeTrue('shaderPrecisionFormat.rangeMin == shaderPrecisionFormat2.rangeMin');
    128 shouldBeTrue('shaderPrecisionFormat.rangeMax == shaderPrecisionFormat2.rangeMax');
    129 shouldBeTrue('shaderPrecisionFormat.precision == shaderPrecisionFormat2.precision');
    130 
    131 debug("");
    132 debug("Test that specified precision matches rendering results");
    133 debug("");
    134 
    135 function testRenderPrecisionSetup(gl, shaderPair) {
    136  const program = wtu.setupProgram(gl, shaderPair);
    137 
    138  // Create a buffer and setup an attribute.
    139  // We wouldn't need this except for a bug in Safari and arguably
    140  // this should be removed from the test but we can't test the test itself
    141  // without until the bug is fixed.
    142  // see https://bugs.webkit.org/show_bug.cgi?id=197592
    143  {
    144    gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
    145    gl.bufferData(gl.ARRAY_BUFFER, 1, gl.STATIC_DRAW);
    146    const loc = gl.getAttribLocation(program, 'position');
    147    gl.enableVertexAttribArray(loc);
    148    gl.vertexAttribPointer(loc, 1, gl.UNSIGNED_BYTE, false, 0, 0);
    149  }
    150 
    151  gl.useProgram(program);
    152 
    153  return program;
    154 }
    155 
    156 function testRenderPrecision(gl, shaderType, type, precision, expected, msg) {
    157  gl.clear(gl.COLOR_BUFFER_BIT);
    158  gl.drawArrays(gl.POINTS, 0, 1);
    159 
    160  const pixel = new Uint8Array(4);
    161  gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
    162 
    163  wtu.checkCanvasRect(gl, 0, 0, 1, 1, expected, msg, 5);
    164 }
    165 
    166 function testRenderPrecisionFloat(gl, precisionEnum, precision) {
    167  function test(gl, shaderPair, shaderType) {
    168    const format = gl.getShaderPrecisionFormat(shaderType, precisionEnum);
    169    const value = 2 ** format.precision - 1;
    170 
    171    const length = v => Math.sqrt(v.reduce((sum, v) => sum + v * v, 0));
    172    const normalize = (v) => {
    173      const l = length(v);
    174      return v.map(v => v / l);
    175    };
    176 
    177    const input = [Math.sqrt(value), Math.sqrt(value), Math.sqrt(value)];
    178    const expected = [...normalize(input).map(v => (v * 0.5 + 0.5) * 255 | 0), 255];
    179 
    180    const msg = `${wtu.glEnumToString(gl, shaderType)}: ${precision} float precision: ${format.precision}, rangeMin: ${format.rangeMin}, rangeMax: ${format.rangeMax}`;
    181    const program = testRenderPrecisionSetup(gl, shaderPair);
    182    const vLocation = gl.getUniformLocation(program, 'v');
    183    gl.uniform3fv(vLocation, input);
    184    testRenderPrecision(gl, shaderType, 'float', precision, expected, msg);
    185  }
    186 
    187  {
    188    const vs = `
    189    attribute vec4 position;
    190    uniform ${precision} vec3 v;
    191    varying ${precision} vec4 v_result;
    192    void main() {
    193      gl_Position = position;
    194      gl_PointSize = 1.0;
    195      v_result = vec4(normalize(v) * 0.5 + 0.5, 1);
    196    }
    197    `;
    198 
    199    const fs = `
    200    precision ${precision} float;
    201    varying ${precision} vec4 v_result;
    202    void main() {
    203      gl_FragColor = v_result;
    204    }
    205    `;
    206 
    207    test(gl, [vs, fs], gl.VERTEX_SHADER);
    208  }
    209 
    210  {
    211    const vs = `
    212    attribute vec4 position;
    213    void main() {
    214      gl_Position = position;
    215      gl_PointSize = 1.0;
    216    }
    217    `;
    218 
    219    const fs = `
    220    precision ${precision} float;
    221    uniform ${precision} vec3 v;
    222    void main() {
    223      gl_FragColor = vec4(normalize(v) * 0.5 + 0.5, 1);
    224    }
    225    `;
    226 
    227    test(gl, [vs, fs], gl.FRAGMENT_SHADER);
    228  }
    229 }
    230 
    231 function testRenderPrecisionInt(gl, precisionEnum, precision) {
    232  function test(gl, shaderPair, shaderType) {
    233    const format = gl.getShaderPrecisionFormat(shaderType, precisionEnum);
    234    const value = 1 << (format.rangeMax - 1);
    235 
    236    const input = [value, value, value, value];
    237    const expected = [255, 255, 255, 255];
    238 
    239    const msg = `${wtu.glEnumToString(gl, shaderType)}: ${precision} int precision: ${format.precision}, rangeMin: ${format.rangeMin}, rangeMax: ${format.rangeMax}`;
    240    const program = testRenderPrecisionSetup(gl, shaderPair);
    241    gl.uniform1i(gl.getUniformLocation(program, 'v'), value);
    242    gl.uniform1f(gl.getUniformLocation(program, 'f'), value);
    243    testRenderPrecision(gl, shaderType, 'int', precision, expected, msg);
    244  }
    245 
    246  {
    247    const vs = `
    248    attribute vec4 position;
    249    uniform ${precision} int v;
    250    uniform highp float f;
    251    varying vec4 v_result;
    252 
    253    void main() {
    254      gl_Position = position;
    255      gl_PointSize = 1.0;
    256      float diff = abs(float(v) - f);
    257      bool pass = diff < 1.0;
    258      v_result = vec4(pass);
    259    }
    260    `;
    261 
    262    const fs = `
    263    precision mediump float;
    264    varying vec4 v_result;
    265    void main() {
    266      gl_FragColor = v_result;
    267    }
    268    `;
    269    test(gl, [vs, fs], gl.VERTEX_SHADER);
    270  }
    271 
    272  {
    273    const vs = `
    274    attribute vec4 position;
    275    void main() {
    276      gl_Position = position;
    277      gl_PointSize = 1.0;
    278    }
    279    `;
    280 
    281    const fs = `
    282    precision ${precision} float;
    283    uniform ${precision} int v;
    284    uniform mediump float f;
    285 
    286    void main() {
    287      mediump float diff = abs(float(v) - f);
    288      bool pass = diff < 1.0;
    289      gl_FragColor = vec4(pass);
    290    }
    291    `;
    292 
    293    test(gl, [vs, fs], gl.FRAGMENT_SHADER);
    294  }
    295 }
    296 
    297 // because the canvas can be 16 bit IIRC
    298 const fb = gl.createFramebuffer(gl.FRAMEBUFFER);
    299 gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
    300 
    301 const tex = gl.createTexture();
    302 gl.bindTexture(gl.TEXTURE_2D, tex);
    303 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
    304 
    305 gl.framebufferTexture2D(
    306    gl.FRAMEBUFFER,
    307    gl.COLOR_ATTACHMENT0,
    308    gl.TEXTURE_2D,
    309    tex,
    310    0);
    311 
    312 gl.viewport(0, 0, 1, 1);
    313 
    314 {
    315  testRenderPrecisionFloat(gl, gl.LOW_FLOAT, 'lowp');
    316  testRenderPrecisionFloat(gl, gl.MEDIUM_FLOAT, 'mediump');
    317 
    318  const format = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT);
    319  if (format.precision !== 0) {
    320    testRenderPrecisionFloat(gl, gl.HIGH_FLOAT, 'highp');
    321  }
    322 }
    323 
    324 {
    325  testRenderPrecisionInt(gl, gl.LOW_INT, 'lowp');
    326  testRenderPrecisionInt(gl, gl.MEDIUM_INT, 'mediump');
    327 
    328  const format = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_INT);
    329  if (format.rangeMax !== 0) {
    330    testRenderPrecisionInt(gl, gl.HIGH_INT, 'highp');
    331  }
    332 }
    333 
    334 finishTest();
    335 </script>
    336 
    337 </body>
    338 </html>