tor-browser

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

shader-uniform-packing-restrictions.html (11827B)


      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 uniform packing restrctions Conformance Test</title>
     12 <link rel="stylesheet" href="../../../resources/js-test-style.css"/>
     13 <link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
     14 <script src="../../../js/js-test-pre.js"></script>
     15 <script src="../../../js/webgl-test-utils.js"></script>
     16 <script src="../../../js/glsl-conformance-test.js"></script>
     17 </head>
     18 <body>
     19 <div id="description"></div>
     20 <div id="console"></div>
     21 <canvas id="example" width="2" height="2"> </canvas>
     22 <script id="vshader" type="x-shader/x-vertex">
     23 attribute vec4 a_position;
     24 void main()
     25 {
     26    gl_Position = a_position;
     27 }
     28 </script>
     29 <script id="fshader" type="x-shader/x-vertex">
     30 precision mediump float;
     31 varying vec4 v_varying;
     32 void main()
     33 {
     34    gl_FragColor = v_varying;
     35 }
     36 </script>
     37 <script id="vshaderArrayTest" type="x-shader/x-vertex">
     38 attribute vec4 a_position;
     39 varying vec4 v_varying;
     40 uniform $(type) u_uniform[$(numTestType)];
     41 void main()
     42 {
     43    v_varying = $(result);
     44    gl_Position = a_position;
     45 }
     46 </script>
     47 <script id="fshaderArrayTest" type="x-shader/x-fragment">
     48 precision mediump float;
     49 uniform $(type) u_uniform[$(numTestType)];
     50 void main()
     51 {
     52    gl_FragColor = $(result);
     53 }
     54 </script>
     55 <script id="vshaderUniformTest" type="x-shader/x-fragment">
     56 attribute vec4 a_position;
     57 varying vec4 v_varying;
     58 $(uniforms)
     59 void main()
     60 {
     61    $(code)
     62    v_varying = $(result);
     63    gl_Position = a_position;
     64 }
     65 </script>
     66 <script id="fshaderUniformTest" type="x-shader/x-fragment">
     67 precision mediump float;
     68 $(uniforms)
     69 void main()
     70 {
     71    $(code)
     72    gl_FragColor = $(result);
     73 }
     74 </script>
     75 <script>
     76 "use strict";
     77 description();
     78 debug("");
     79 var wtu = WebGLTestUtils;
     80 var gl = wtu.create3DContext("example");
     81 
     82 var uniformTypes = [
     83  { type: "bool",        componentsPerRow: 1, rows: 1, fType: "float", uniToF: "float(u_uniform$(id)$(index))", fToVec4: "vec4($(f), 0, 0, 0)"},
     84  { type: "float",       componentsPerRow: 1, rows: 1, fType: "float", uniToF: "u_uniform$(id)$(index)", fToVec4: "vec4($(f), 0, 0, 0)"},
     85  { type: "int",         componentsPerRow: 1, rows: 1, fType: "float", uniToF: "float(u_uniform$(id)$(index))", fToVec4: "vec4($(f), 0, 0, 0)"},
     86  { type: "vec2",        componentsPerRow: 2, rows: 1, fType: "vec2",  uniToF: "u_uniform$(id)$(index)", fToVec4: "vec4($(f), 0, 0)"},
     87  { type: "ivec2",       componentsPerRow: 2, rows: 1, fType: "vec2",  uniToF: "vec2(u_uniform$(id)$(index))", fToVec4: "vec4($(f), 0, 0)"},
     88  { type: "bvec2",       componentsPerRow: 2, rows: 1, fType: "vec2",  uniToF: "vec2(u_uniform$(id)$(index))", fToVec4: "vec4($(f), 0, 0)"},
     89  { type: "vec3",        componentsPerRow: 3, rows: 1, fType: "vec3",  uniToF: "u_uniform$(id)$(index)", fToVec4: "vec4($(f), 0)"},
     90  { type: "ivec3",       componentsPerRow: 3, rows: 1, fType: "vec3",  uniToF: "vec3(u_uniform$(id)$(index))", fToVec4: "vec4($(f), 0)"},
     91  { type: "bvec3",       componentsPerRow: 3, rows: 1, fType: "vec3",  uniToF: "vec3(u_uniform$(id)$(index))", fToVec4: "vec4($(f), 0)"},
     92  { type: "vec4",        componentsPerRow: 4, rows: 1, fType: "vec4",  uniToF: "u_uniform$(id)$(index)", fToVec4: "$(f)"},
     93  { type: "ivec4",       componentsPerRow: 4, rows: 1, fType: "vec4",  uniToF: "vec4(u_uniform$(id)$(index))", fToVec4: "$(f)"},
     94  { type: "bvec4",       componentsPerRow: 4, rows: 1, fType: "vec4",  uniToF: "vec4(u_uniform$(id)$(index))", fToVec4: "$(f)"},
     95 // Yes, the spec says mat2 takes 4 columns, 2 rows.
     96  { type: "mat2",        componentsPerRow: 4, rows: 2, fType: "vec2",  uniToF: "vec2(u_uniform$(id)$(index)[0])", fToVec4: "vec4($(f), 0, 0)"},
     97  { type: "mat3",        componentsPerRow: 3, rows: 3, fType: "vec3",  uniToF: "vec3(u_uniform$(id)$(index)[0])", fToVec4: "vec4($(f), 0)"},
     98  { type: "mat4",        componentsPerRow: 4, rows: 4, fType: "vec4",  uniToF: "vec4(u_uniform$(id)$(index)[0])", fToVec4: "$(f)"},
     99 // Samplers generally have more restrictive limits.
    100 //  { type: "sampler2D",   componentsPerRow: 1, rows: 1, code: "vec4(texture2D(u_uniform[$(index)], vec2(0, 0)))", },
    101 //  { type: "samplerCube", componentsPerRow: 1, rows: 1, code: "vec4(textureCube(u_uniform[$(index)], vec3(0, 0, 0)))", },
    102 ];
    103 
    104 var vBaseSource = wtu.getScript("vshader");
    105 var fBaseSource = wtu.getScript("fshader");
    106 var vArrayTestSource = wtu.getScript("vshaderArrayTest");
    107 var fArrayTestSource = wtu.getScript("fshaderArrayTest");
    108 var vUniformTestSource = wtu.getScript("vshaderUniformTest");
    109 var fUniformTestSource = wtu.getScript("fshaderUniformTest");
    110 
    111 var tests = [];
    112 var shaderTypes = [
    113  { type: "vertex",
    114    // For tests that expect failure which shader might fail.
    115    vertExpectation: false,
    116    fragExpectation: true,
    117    vertArrayTest: vArrayTestSource,
    118    fragArrayTest: fBaseSource,
    119    vertUniformTest: vUniformTestSource,
    120    fragUniformTest: fBaseSource,
    121    maxVectors: gl.getParameter(gl.MAX_VERTEX_UNIFORM_VECTORS),
    122    minVectors: 127,  // GLSL ES 1.0.17 Appendix A.7 and A.8. Reserve one row for constants in the code, hence 128 - 1.
    123  },
    124  { type: "fragment",
    125    // For tests that expect failure which shader might fail.
    126    vertExpectation: true,
    127    fragExpectation: false,
    128    vertArrayTest: vBaseSource,
    129    fragArrayTest: fArrayTestSource,
    130    vertUniformTest: vBaseSource,
    131    fragUniformTest: fUniformTestSource,
    132    maxVectors: gl.getParameter(gl.MAX_FRAGMENT_UNIFORM_VECTORS),
    133    minVectors: 15,  // GLSL ES 1.0.17 Appendix A.8 - minimum value of gl_maxFragmentUniformVectors is 16. Again, reserve a row for constants.
    134  },
    135 ];
    136 for (var ss = 0; ss < shaderTypes.length; ++ss) {
    137  var shaderType = shaderTypes[ss];
    138  debug("max " + shaderType.type + ": " + shaderType.maxVectors);
    139  for (var ii = 0; ii < uniformTypes.length; ++ii) {
    140    var info = uniformTypes[ii];
    141    wtu.log("checking: " + info.type);
    142    // Compute the maximum amount of this type allowed in a single array.
    143    var maxInArray = Math.floor(shaderType.maxVectors / info.rows);
    144    // Compute the minimum required to work in a single array.
    145    var minVars = Math.floor(shaderType.minVectors / info.rows);
    146    // Compute the maximum allowed as single elements
    147    var maxPerRow = Math.floor(4 / info.componentsPerRow);
    148    var maxPacked = Math.floor(shaderType.maxVectors * maxPerRow / info.rows);
    149 
    150    // Test array[1] of the type
    151    var uniToF = wtu.replaceParams(info.uniToF, {id: "", index: "[0]"});
    152    var vec4 = wtu.replaceParams(info.fToVec4, {f: uniToF});
    153    tests.push({
    154      vShaderSource: wtu.replaceParams(shaderType.vertArrayTest, {numTestType: 1, result: vec4}, info),
    155      vShaderSuccess: true,
    156      fShaderSource: wtu.replaceParams(shaderType.fragArrayTest, {numTestType: 1, result: vec4}, info),
    157      fShaderSuccess: true,
    158      linkSuccess: true,
    159      passMsg: shaderType.type + " shader with uniform array of " + info.type + " with 1 element should succeed",
    160    });
    161 
    162    // Note: We can't test an array filling all uniform space as actual GL drivers are
    163    // only required to be able to do the minimum number. After that it can fail for
    164    // multiple reasons, including uniform registers being reserved for the implementation's
    165    // own use. Constants also take up uniform registers.
    166 
    167    // Test required number of uniforms
    168    var uniToF = wtu.replaceParams(info.uniToF, {id: "", index: "[" + (minVars - 1) + "]"});
    169    var vec4 = wtu.replaceParams(info.fToVec4, {f: uniToF});
    170    tests.push({
    171      vShaderSource: wtu.replaceParams(shaderType.vertArrayTest, {numTestType: minVars, result: vec4}, info),
    172      vShaderSuccess: true,
    173      fShaderSource: wtu.replaceParams(shaderType.fragArrayTest, {numTestType: minVars, result: vec4}, info),
    174      fShaderSuccess: true,
    175      linkSuccess: true,
    176      passMsg: shaderType.type + " shader with uniform array of " + info.type + " with " + minVars + " elements (the minimum required) should succeed",
    177    });
    178 
    179    // Test array[max + 1] accessing last element. WebGL requires this to fail.
    180    var uniToF = wtu.replaceParams(info.uniToF, {id: "", index: "[" + maxInArray + "]"});
    181    var vec4 = wtu.replaceParams(info.fToVec4, {f: uniToF});
    182    tests.push({
    183      vShaderSource: wtu.replaceParams(shaderType.vertArrayTest, {numTestType: maxInArray + 1, result: vec4}, info),
    184      vShaderSuccess: shaderType.vertExpectation,
    185      fShaderSource: wtu.replaceParams(shaderType.fragArrayTest, {numTestType: maxInArray + 1, result: vec4}, info),
    186      fShaderSuccess: shaderType.fragExpectation,
    187      linkSuccess: false,
    188      passMsg: shaderType.type + " shader with uniform array of " + info.type + " with " + (maxInArray + 1) + " elements (one past maximum) accessing last element should fail",
    189    });
    190 
    191    // Test array[max + 1] accessing first element. WebGL requires this to fail but ES allows truncating array.
    192    var uniToF = wtu.replaceParams(info.uniToF, {id: "", index: "[0]"});
    193    var vec4 = wtu.replaceParams(info.fToVec4, {f: uniToF});
    194    tests.push({
    195      vShaderSource: wtu.replaceParams(shaderType.vertArrayTest, {numTestType: maxInArray + 1, result: vec4}, info),
    196      vShaderSuccess: shaderType.vertExpectation,
    197      fShaderSource: wtu.replaceParams(shaderType.fragArrayTest, {numTestType: maxInArray + 1, result: vec4}, info),
    198      fShaderSuccess: shaderType.fragExpectation,
    199      linkSuccess: false,
    200      passMsg: shaderType.type + " shader with uniform array of " + info.type + " with " + (maxInArray + 1) + " elements (one past maximum) accessing first element should fail",
    201    });
    202 
    203    // Note: We can't test max uniforms as actual GL drivers are only required to be able
    204    // to do the minimum number. After that it can fail for multiple reasons, including
    205    // uniform registers being reserved for the implementation's own use or also instruction
    206    // space limitations. Strictly speaking, guaranteed supported length of a shader
    207    // executable is defined by the GLES2 conformance tests according to GLSL ES 1.0.17
    208    // Appendix A.2. This does not give us an exact limit: this test only aims to fit within
    209    // instruction space limits imposed by existing GLES2 compliant hardware.
    210 
    211    var generateCode = function(numVars) {
    212      var uniforms = [];
    213      var sumTerms = [];
    214      for (var uu = 0; uu < numVars; ++uu) {
    215        uniforms.push("    uniform " + info.type + " u_uniform" + uu + ";");
    216        sumTerms.push(wtu.replaceParams(info.uniToF, {id: uu, index: ""}));
    217      }
    218      return {
    219        uniforms: uniforms.join("\n"),
    220        code: info.fType + " sum = " + sumTerms.join(" + \n            ") + ";",
    221        result: wtu.replaceParams(info.fToVec4, {f: 'sum'})
    222      };
    223    };
    224 
    225    // Test max+1 uniforms of type.
    226    tests.push({
    227      vShaderSource: wtu.replaceParams(shaderType.vertUniformTest, generateCode(maxPacked + 1), info),
    228      vShaderSuccess: shaderType.vertExpectation,
    229      fShaderSource: wtu.replaceParams(shaderType.fragUniformTest, generateCode(maxPacked + 1), info),
    230      fShaderSuccess: shaderType.fragExpectation,
    231      linkSuccess: false,
    232      passMsg: shaderType.type + " shader with " + (maxPacked + 1) + " uniforms of " + info.type + " (one past maximum) should fail",
    233    });
    234 
    235    // Test required uniforms of type.
    236    tests.push({
    237      vShaderSource: wtu.replaceParams(shaderType.vertUniformTest, generateCode(minVars), info),
    238      vShaderSuccess: true,
    239      fShaderSource: wtu.replaceParams(shaderType.fragUniformTest, generateCode(minVars), info),
    240      fShaderSuccess: true,
    241      linkSuccess: true,
    242      passMsg: shaderType.type + " shader with " + minVars + " uniforms of " + info.type + " (the minimum required) should succeed",
    243    });
    244  }
    245 }
    246 GLSLConformanceTester.runTests(tests);
    247 var successfullyParsed = true;
    248 </script>
    249 </body>
    250 </html>