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.
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>
18 <div id=
"description"></div>
19 <div id=
"console"></div>
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.
24 <script type=
"application/javascript">
26 description(
"Indexing complex array expressions");
29 // All the templates run the given sequence:
30 //
1. loopExpression or loopCondition
32 //
3. Break loop if it's done loopIterations iterations, else go back to
1.
34 var forLoopExpressionTemplate = [
36 'precision mediump float;',
38 '$(globalScopePrefix)',
41 ' for (int i =
0; true; $(loopExpression))',
46 ' if (i
> $(loopIterations)) { break; }',
49 ' color = ($(passCondition)) ? vec4(
0,
1.0,
0,
1.0) : vec4(
1.0,
0,
0,
1.0);',
53 var forLoopConditionTemplate = [
55 'precision mediump float;',
57 '$(globalScopePrefix)',
60 ' for (int i =
1; $(loopCondition); ++i)',
63 ' if (i
>= $(loopIterations)) { break; }',
65 ' color = ($(passCondition)) ? vec4(
0,
1.0,
0,
1.0) : vec4(
1.0,
0,
0,
1.0);',
69 var whileLoopConditionTemplate = [
71 'precision mediump float;',
73 '$(globalScopePrefix)',
77 ' while ($(loopCondition))',
81 ' if (i
>= $(loopIterations)) { break; }',
83 ' color = ($(passCondition)) ? vec4(
0,
1.0,
0,
1.0) : vec4(
1.0,
0,
0,
1.0);',
87 var doWhileLoopConditionTemplate = [
89 'precision mediump float;',
91 '$(globalScopePrefix)',
95 // Run the loop condition one extra time to make the different test types behave the same
100 ' if (i
>= $(loopIterations)) { break; }',
102 ' while ($(loopCondition));',
103 ' color = ($(passCondition)) ? vec4(
0,
1.0,
0,
1.0) : vec4(
1.0,
0,
0,
1.0);',
109 description: 'indexing an array assignment',
110 globalScopePrefix: '',
112 'float a[
2] = float[
2](
0.0,
0.0);',
113 'float b[
2] = float[
2](
2.0,
1.0);',
116 loopExpression: 'c = (a = b)[
0]',
117 loopCondition: 'bool((c = (a = b)[
0]) +
1.0)',
118 loopContents: 'b[
0] +=
1.0;',
120 passCondition: 'abs(c -
4.0) <
0.01'
123 description: 'indexing a function returning an array',
125 'int sideEffectCounter =
0;',
126 'float[
2] functionReturnArray() {',
127 ' ++sideEffectCounter;',
128 ' return float[
2](float(sideEffectCounter),
1.0);',
131 mainPrefix: 'float c =
0.0;',
132 loopExpression: 'c = functionReturnArray()[
0]',
133 loopCondition: 'bool(c = functionReturnArray()[
0])',
136 passCondition: 'abs(c -
3.0) <
0.01 && sideEffectCounter ==
3'
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])',
146 passCondition: 'c ==
6'
149 description: 'indexing an array constructor inside a sequence operator',
151 'int sideEffectCounter =
0;',
153 ' sideEffectCounter++;',
154 ' return sideEffectCounter;',
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]))',
162 passCondition: 'c ==
6 && sideEffectCounter ==
3'
165 description: 'dynamic indexing of a vector',
166 globalScopePrefix: '',
168 'vec4 v = vec4(
1.0,
2.0,
3.0,
4.0);',
172 loopExpression: 'c = v[j]',
173 loopCondition: 'bool(c = v[j])',
174 loopContents: '++j;',
176 passCondition: 'abs(c -
3.0) <
0.01'
179 description: 'short-circuiting operator',
181 'int sideEffectCounter =
0;',
183 ' sideEffectCounter++;',
184 ' return sideEffectCounter
> 0;',
188 loopExpression: 'func() && func()',
189 loopCondition: 'func() && func()',
192 passCondition: 'sideEffectCounter ==
6'
195 description: 'short-circuiting operator',
197 'int sideEffectCounter =
0;',
199 ' sideEffectCounter++;',
200 ' return sideEffectCounter
> 0;',
204 loopExpression: 'func() || func()',
205 loopCondition: 'func() || func()',
208 passCondition: 'sideEffectCounter ==
3'
211 description: 'short-circuiting operator',
213 'int sideEffectCounterA =
0;',
215 ' sideEffectCounterA++;',
216 ' return sideEffectCounterA
> 1;',
218 'int sideEffectCounterB =
0;',
220 ' sideEffectCounterB++;',
221 ' return sideEffectCounterB
> 0;',
225 loopExpression: 'funcA() ? true : funcB()',
226 loopCondition: 'funcA() ? true : funcB()',
229 passCondition: 'sideEffectCounterA ==
3 && sideEffectCounterB ==
1'
232 description: 'high-precision constant',
234 'const highp float f =
2048.5;',
235 'uniform mediump float u_zero;'
237 mainPrefix: 'float c =
0.0;',
238 loopExpression: 'c = fract(u_zero + f)',
239 loopCondition: 'bool(c = fract(u_zero + f))',
242 passCondition: 'abs(c -
0.5) <
0.01'
245 description: 'l-value indexing side effects combined with static indexing of a vector',
247 'int sideEffectCounter =
0;',
249 ' sideEffectCounter++;',
250 ' return sideEffectCounter
> 1 ?
1 :
0;',
258 loopExpression: 'V[func()][
0]++',
259 loopCondition: 'bool(V[func()][
0]++)',
262 passCondition: 'abs(V[
0][
0] -
2.0) <
0.01 && abs(V[
1][
0] -
5.0) <
0.01 && sideEffectCounter ==
3'
265 description: 'l-value indexing side effects combined with dynamically indexing a vector',
267 'int sideEffectCounter =
0;',
268 'uniform int u_zero;',
270 ' sideEffectCounter++;',
271 ' return sideEffectCounter
> 1 ?
1 :
0;',
279 loopExpression: 'V[func()][u_zero +
1]++',
280 loopCondition: 'bool(V[func()][u_zero +
1]++)',
283 passCondition: 'abs(V[
0][
1] -
2.0) <
0.01 && abs(V[
1][
1] -
5.0) <
0.01 && sideEffectCounter ==
3'
289 var wtu = WebGLTestUtils;
291 for (var i =
0; i < testDataList.length; ++i) {
292 var testData = testDataList[i];
293 if ('loopCondition' in testData) {
295 fShaderSource: wtu.replaceParams(forLoopConditionTemplate, testData),
296 fShaderSuccess: true,
298 passMsg: 'Test ' + testData.description + ': ' + testData.loopCondition + ' inside a for loop condition'
301 fShaderSource: wtu.replaceParams(whileLoopConditionTemplate, testData),
302 fShaderSuccess: true,
304 passMsg: 'Test ' + testData.description + ': ' + testData.loopCondition + ' inside a while loop condition'
307 fShaderSource: wtu.replaceParams(doWhileLoopConditionTemplate, testData),
308 fShaderSuccess: true,
310 passMsg: 'Test ' + testData.description + ': ' + testData.loopCondition + ' inside a do-while loop condition'
313 if ('loopExpression' in testData) {
315 fShaderSource: wtu.replaceParams(forLoopExpressionTemplate, testData),
316 fShaderSuccess: true,
318 passMsg: 'Test ' + testData.description + ': ' + testData.loopExpression + ' inside a for loop expression'
323 GLSLConformanceTester.runRenderTests(tests,
2);