tor-browser

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

tricky-loop-conditions.html (10228B)


      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>GLSL tricky loop conditions and loop expressions</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 <script src="../../js/glsl-conformance-test.js"></script>
     16 </head>
     17 <body>
     18 <div id="description"></div>
     19 <div id="console"></div>
     20 <!--
     21 Some tricky shader expressions might be subject to syntax tree transformations that need to create
     22 new statements. Ensure that these expressions also work inside loop conditions and loop expressions.
     23 -->
     24 <script type="application/javascript">
     25 "use strict";
     26 description("Indexing complex array expressions");
     27 debug("");
     28 
     29 // All the templates run the given sequence:
     30 // 1. loopExpression or loopCondition
     31 // 2. loopContents
     32 // 3. Break loop if it's done loopIterations iterations, else go back to 1.
     33 
     34 var forLoopExpressionTemplate = [
     35    '#version 300 es',
     36    'precision mediump float;',
     37    'out vec4 color;',
     38    '$(globalScopePrefix)',
     39    'void main() {',
     40    '$(mainPrefix)',
     41    '  for (int i = 0; true; $(loopExpression))',
     42    '  {',
     43    '    ++i;',
     44    '    if (i > 1) {',
     45    '      $(loopContents)',
     46    '      if (i > $(loopIterations)) { break; }',
     47    '    }',
     48    '  }',
     49    '  color = ($(passCondition)) ? vec4(0, 1.0, 0, 1.0) : vec4(1.0, 0, 0, 1.0);',
     50    '}'
     51 ].join('\n');
     52 
     53 var forLoopConditionTemplate = [
     54    '#version 300 es',
     55    'precision mediump float;',
     56    'out vec4 color;',
     57    '$(globalScopePrefix)',
     58    'void main() {',
     59    '$(mainPrefix)',
     60    '  for (int i = 1; $(loopCondition); ++i)',
     61    '  {',
     62    '    $(loopContents)',
     63    '    if (i >= $(loopIterations)) { break; }',
     64    '  }',
     65    '  color = ($(passCondition)) ? vec4(0, 1.0, 0, 1.0) : vec4(1.0, 0, 0, 1.0);',
     66    '}'
     67 ].join('\n');
     68 
     69 var whileLoopConditionTemplate = [
     70    '#version 300 es',
     71    'precision mediump float;',
     72    'out vec4 color;',
     73    '$(globalScopePrefix)',
     74    'void main() {',
     75    '$(mainPrefix)',
     76    '  int i = 0;',
     77    '  while ($(loopCondition))',
     78    '  {',
     79    '    $(loopContents)',
     80    '    ++i;',
     81    '    if (i >= $(loopIterations)) { break; }',
     82    '  }',
     83    '  color = ($(passCondition)) ? vec4(0, 1.0, 0, 1.0) : vec4(1.0, 0, 0, 1.0);',
     84    '}'
     85 ].join('\n');
     86 
     87 var doWhileLoopConditionTemplate = [
     88    '#version 300 es',
     89    'precision mediump float;',
     90    'out vec4 color;',
     91    '$(globalScopePrefix)',
     92    'void main() {',
     93    '$(mainPrefix)',
     94    '  int i = 0;',
     95    // Run the loop condition one extra time to make the different test types behave the same
     96    '  $(loopCondition);',
     97    '  do {',
     98    '    $(loopContents)',
     99    '    ++i;',
    100    '    if (i >= $(loopIterations)) { break; }',
    101    '  }',
    102    '  while ($(loopCondition));',
    103    '  color = ($(passCondition)) ? vec4(0, 1.0, 0, 1.0) : vec4(1.0, 0, 0, 1.0);',
    104    '}'
    105 ].join('\n');
    106 
    107 var testDataList = [
    108 {
    109    description: 'indexing an array assignment',
    110    globalScopePrefix: '',
    111    mainPrefix: [
    112            'float a[2] = float[2](0.0, 0.0);',
    113            'float b[2] = float[2](2.0, 1.0);',
    114            'float c = 0.0;'
    115        ].join('\n'),
    116    loopExpression: 'c = (a = b)[0]',
    117    loopCondition: 'bool((c = (a = b)[0]) + 1.0)',
    118    loopContents: 'b[0] += 1.0;',
    119    loopIterations: 3,
    120    passCondition: 'abs(c - 4.0) < 0.01'
    121 },
    122 {
    123    description: 'indexing a function returning an array',
    124    globalScopePrefix: [
    125            'int sideEffectCounter = 0;',
    126            'float[2] functionReturnArray() {',
    127            '  ++sideEffectCounter;',
    128            '  return float[2](float(sideEffectCounter), 1.0);',
    129            '}'
    130        ].join('\n'),
    131    mainPrefix: 'float c = 0.0;',
    132    loopExpression: 'c = functionReturnArray()[0]',
    133    loopCondition: 'bool(c = functionReturnArray()[0])',
    134    loopContents: '',
    135    loopIterations: 3,
    136    passCondition: 'abs(c - 3.0) < 0.01 && sideEffectCounter == 3'
    137 },
    138 {
    139    description: 'indexing an array constructor',
    140    globalScopePrefix: '',
    141    mainPrefix: 'int c = 0;',
    142    loopExpression: 'c = (int[2](c + 1, c + 2))[1]',
    143    loopCondition: 'bool(c = (int[2](c + 1, c + 2))[1])',
    144    loopContents: '',
    145    loopIterations: 3,
    146    passCondition: 'c == 6'
    147 },
    148 {
    149    description: 'indexing an array constructor inside a sequence operator',
    150    globalScopePrefix: [
    151            'int sideEffectCounter = 0;',
    152            'int func() {',
    153            '  sideEffectCounter++;',
    154            '  return sideEffectCounter;',
    155            '}'
    156        ].join('\n'),
    157    mainPrefix: 'int c = 0;',
    158    loopExpression: 'c = (func(), (int[2](c + 1, c + 2))[1])',
    159    loopCondition: 'bool(c = (func(), (int[2](c + 1, c + 2))[1]))',
    160    loopContents: '',
    161    loopIterations: 3,
    162    passCondition: 'c == 6 && sideEffectCounter == 3'
    163 },
    164 {
    165    description: 'dynamic indexing of a vector',
    166    globalScopePrefix: '',
    167    mainPrefix: [
    168            'vec4 v = vec4(1.0, 2.0, 3.0, 4.0);',
    169            'float c = 0.0;',
    170            'int j = 0;'
    171        ].join('\n'),
    172    loopExpression: 'c = v[j]',
    173    loopCondition: 'bool(c = v[j])',
    174    loopContents: '++j;',
    175    loopIterations: 3,
    176    passCondition: 'abs(c - 3.0) < 0.01'
    177 },
    178 {
    179    description: 'short-circuiting operator',
    180    globalScopePrefix: [
    181            'int sideEffectCounter = 0;',
    182            'bool func() {',
    183            '  sideEffectCounter++;',
    184            '  return sideEffectCounter > 0;',
    185            '}'
    186        ].join('\n'),
    187    mainPrefix: '',
    188    loopExpression: 'func() && func()',
    189    loopCondition: 'func() && func()',
    190    loopContents: '',
    191    loopIterations: 3,
    192    passCondition: 'sideEffectCounter == 6'
    193 },
    194 {
    195    description: 'short-circuiting operator',
    196    globalScopePrefix: [
    197            'int sideEffectCounter = 0;',
    198            'bool func() {',
    199            '  sideEffectCounter++;',
    200            '  return sideEffectCounter > 0;',
    201            '}'
    202        ].join('\n'),
    203    mainPrefix: '',
    204    loopExpression: 'func() || func()',
    205    loopCondition: 'func() || func()',
    206    loopContents: '',
    207    loopIterations: 3,
    208    passCondition: 'sideEffectCounter == 3'
    209 },
    210 {
    211    description: 'short-circuiting operator',
    212    globalScopePrefix: [
    213            'int sideEffectCounterA = 0;',
    214            'bool funcA() {',
    215            '  sideEffectCounterA++;',
    216            '  return sideEffectCounterA > 1;',
    217            '}',
    218            'int sideEffectCounterB = 0;',
    219            'bool funcB() {',
    220            '  sideEffectCounterB++;',
    221            '  return sideEffectCounterB > 0;',
    222            '}'
    223        ].join('\n'),
    224    mainPrefix: '',
    225    loopExpression: 'funcA() ? true : funcB()',
    226    loopCondition: 'funcA() ? true : funcB()',
    227    loopContents: '',
    228    loopIterations: 3,
    229    passCondition: 'sideEffectCounterA == 3 && sideEffectCounterB == 1'
    230 },
    231 {
    232    description: 'high-precision constant',
    233    globalScopePrefix: [
    234            'const highp float f = 2048.5;',
    235            'uniform mediump float u_zero;'
    236        ].join('\n'),
    237    mainPrefix: 'float c = 0.0;',
    238    loopExpression: 'c = fract(u_zero + f)',
    239    loopCondition: 'bool(c = fract(u_zero + f))',
    240    loopContents: '',
    241    loopIterations: 3,
    242    passCondition: 'abs(c - 0.5) < 0.01'
    243 },
    244 {
    245    description: 'l-value indexing side effects combined with static indexing of a vector',
    246    globalScopePrefix: [
    247            'int sideEffectCounter = 0;',
    248            'int func() {',
    249            '  sideEffectCounter++;',
    250            '  return sideEffectCounter > 1 ? 1 : 0;',
    251            '}'
    252        ].join('\n'),
    253    mainPrefix: [
    254            'vec4[2] V;',
    255            'V[0] = vec4(1.0);',
    256            'V[1] = vec4(3.0);'
    257        ].join('\n'),
    258    loopExpression: 'V[func()][0]++',
    259    loopCondition: 'bool(V[func()][0]++)',
    260    loopContents: '',
    261    loopIterations: 3,
    262    passCondition: 'abs(V[0][0] - 2.0) < 0.01 && abs(V[1][0] - 5.0) < 0.01 && sideEffectCounter == 3'
    263 },
    264 {
    265    description: 'l-value indexing side effects combined with dynamically indexing a vector',
    266    globalScopePrefix: [
    267            'int sideEffectCounter = 0;',
    268            'uniform int u_zero;',
    269            'int func() {',
    270            '  sideEffectCounter++;',
    271            '  return sideEffectCounter > 1 ? 1 : 0;',
    272            '}'
    273        ].join('\n'),
    274    mainPrefix: [
    275            'vec4[2] V;',
    276            'V[0] = vec4(1.0);',
    277            'V[1] = vec4(3.0);'
    278        ].join('\n'),
    279    loopExpression: 'V[func()][u_zero + 1]++',
    280    loopCondition: 'bool(V[func()][u_zero + 1]++)',
    281    loopContents: '',
    282    loopIterations: 3,
    283    passCondition: 'abs(V[0][1] - 2.0) < 0.01 && abs(V[1][1] - 5.0) < 0.01 && sideEffectCounter == 3'
    284 }
    285 ];
    286 
    287 var tests = [];
    288 
    289 var wtu = WebGLTestUtils;
    290 
    291 for (var i = 0; i < testDataList.length; ++i) {
    292    var testData = testDataList[i];
    293    if ('loopCondition' in testData) {
    294        tests.push({
    295            fShaderSource: wtu.replaceParams(forLoopConditionTemplate, testData),
    296            fShaderSuccess: true,
    297            linkSuccess: true,
    298            passMsg: 'Test ' + testData.description + ': ' + testData.loopCondition + ' inside a for loop condition'
    299        });
    300        tests.push({
    301            fShaderSource: wtu.replaceParams(whileLoopConditionTemplate, testData),
    302            fShaderSuccess: true,
    303            linkSuccess: true,
    304            passMsg: 'Test ' + testData.description + ': ' + testData.loopCondition + ' inside a while loop condition'
    305        });
    306        tests.push({
    307            fShaderSource: wtu.replaceParams(doWhileLoopConditionTemplate, testData),
    308            fShaderSuccess: true,
    309            linkSuccess: true,
    310            passMsg: 'Test ' + testData.description + ': ' + testData.loopCondition + ' inside a do-while loop condition'
    311        });
    312    }
    313    if ('loopExpression' in testData) {
    314        tests.push({
    315            fShaderSource: wtu.replaceParams(forLoopExpressionTemplate, testData),
    316            fShaderSuccess: true,
    317            linkSuccess: true,
    318            passMsg: 'Test ' + testData.description + ': ' + testData.loopExpression + ' inside a for loop expression'
    319        });
    320    }
    321 }
    322 
    323 GLSLConformanceTester.runRenderTests(tests, 2);
    324 
    325 </script>
    326 </body>
    327 </html>