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>Indexing with a constant expression should compile only if the index is in range
</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 <script id=
"VertexArrayTemplate" type=
"x-shader/x-vertex">
18 precision mediump float;
25 float c = ua[$(constantExpression)];
26 gl_Position = vec4(c);
29 <script id=
"FragmentArrayTemplate" type=
"x-shader/x-fragment">
30 precision mediump float;
37 float c = ua[$(constantExpression)];
38 gl_FragColor = vec4(c);
41 <script id=
"VertexVectorTemplate" type=
"x-shader/x-vertex">
42 precision mediump float;
49 float c = uv[$(constantExpression)];
50 gl_Position = vec4(c);
53 <script id=
"FragmentVectorTemplate" type=
"x-shader/x-fragment">
54 precision mediump float;
61 float c = uv[$(constantExpression)];
62 gl_FragColor = vec4(c);
65 <script id=
"VertexMatrixTemplate" type=
"x-shader/x-vertex">
66 precision mediump float;
73 float c = um[$(constantExpression)].x;
74 gl_Position = vec4(c);
77 <script id=
"FragmentMatrixTemplate" type=
"x-shader/x-fragment">
78 precision mediump float;
85 float c = um[$(constantExpression)].x;
86 gl_FragColor = vec4(c);
90 <body onload=
"runTest()">
91 <div id=
"description"></div>
92 <div id=
"console"></div>
93 <script type=
"application/javascript">
97 var wtu = WebGLTestUtils;
99 // ESSL
1.00 section
4.1.9 Arrays
100 // It is illegal to index an array with an integral constant expression greater than or equal to its
101 // declared size. It is also illegal to index an array with a negative constant expression.
103 // ESSL
1.00 section
5.5 Vector Components
104 // Reading from or writing to a vector using a constant integral expression with a value that is negative
105 // or greater than or equal to the size of the vector is illegal.
107 // ESSL
1.00 section
5.6 Matrix components
108 // The behavior when accessing a component outside the bounds of a matrix are the same as those for
109 // vectors and arrays. The compiler must generate an error if the index expression is a constant expression.
111 // ESSL
1.00 spec section
5.10.
112 // A constant expression is one of
113 // * a literal value (e.g.,
5 or true)
114 // * a global or local variable qualified as const excluding function parameters
115 // * an expression formed by an operator on operands that are constant expressions, including getting
116 // an element of a constant vector or a constant matrix, or a field of a constant structure
117 // * a constructor whose arguments are all constant expressions
118 // * a built-in function call whose arguments are all constant expressions, with the exception of the
119 // texture lookup functions.
121 var runTest = function() {
122 var vsArrayTemplate = document.getElementById('VertexArrayTemplate').text;
123 var fsArrayTemplate = document.getElementById('FragmentArrayTemplate').text;
124 var vsVectorTemplate = document.getElementById('VertexVectorTemplate').text;
125 var fsVectorTemplate = document.getElementById('FragmentVectorTemplate').text;
126 var vsMatrixTemplate = document.getElementById('VertexMatrixTemplate').text;
127 var fsMatrixTemplate = document.getElementById('FragmentMatrixTemplate').text;
131 var pushTest = function(constantExpression, expectSuccess, opt_init) {
132 if (opt_init === undefined) {
136 vShaderSource: wtu.replaceParams(vsArrayTemplate, {constantExpression: constantExpression, init: opt_init}),
137 vShaderSuccess: expectSuccess,
138 linkSuccess: expectSuccess,
139 passMsg:
"Using " + constantExpression +
" as an index for an array with size 4 in a vertex shader should " + (expectSuccess ?
"compile." :
"fail compilation.")
142 fShaderSource: wtu.replaceParams(fsArrayTemplate, {constantExpression: constantExpression, init: opt_init}),
143 fShaderSuccess: expectSuccess,
144 linkSuccess: expectSuccess,
145 passMsg:
"Using " + constantExpression +
" as an index for an array with size 4 in a fragment shader should " + (expectSuccess ?
"compile." :
"fail compilation.")
148 vShaderSource: wtu.replaceParams(vsVectorTemplate, {constantExpression: constantExpression, init: opt_init}),
149 vShaderSuccess: expectSuccess,
150 linkSuccess: expectSuccess,
151 passMsg:
"Using " + constantExpression +
" as a vec4 index in a vertex shader should " + (expectSuccess ?
"compile." :
"fail compilation.")
154 fShaderSource: wtu.replaceParams(fsVectorTemplate, {constantExpression: constantExpression, init: opt_init}),
155 fShaderSuccess: expectSuccess,
156 linkSuccess: expectSuccess,
157 passMsg:
"Using " + constantExpression +
" as a vec4 index in a fragment shader should " + (expectSuccess ?
"compile." :
"fail compilation.")
160 vShaderSource: wtu.replaceParams(vsMatrixTemplate, {constantExpression: constantExpression, init: opt_init}),
161 vShaderSuccess: expectSuccess,
162 linkSuccess: expectSuccess,
163 passMsg:
"Using " + constantExpression +
" as a mat4 index in a vertex shader should " + (expectSuccess ?
"compile." :
"fail compilation.")
166 fShaderSource: wtu.replaceParams(fsMatrixTemplate, {constantExpression: constantExpression, init: opt_init}),
167 fShaderSuccess: expectSuccess,
168 linkSuccess: expectSuccess,
169 passMsg:
"Using " + constantExpression +
" as a mat4 index in a fragment shader should " + (expectSuccess ?
"compile." :
"fail compilation.")
175 pushTest('-
1', false);
176 pushTest('
4', false);
177 pushTest('
2 +
2', false);
178 pushTest('
6 -
2', false);
179 pushTest('
2 *
2', false);
180 pushTest('
8 /
2', false);
181 pushTest('int(true) *
4', false);
182 pushTest('ivec4(
4).x', false);
183 pushTest('ivec4(
4)[
0]', false);
184 pushTest('int(vec4(
5.0).x)', false);
185 pushTest('int(mat4(
5.0)[
0].x)', false);
187 pushTest('int(radians(
360.0))', false);
188 pushTest('int(degrees(
1.0))', false);
189 pushTest('int(
5.0 + sin(
0.0))', false);
190 pushTest('int(
5.0 + asin(
0.0))', false);
191 pushTest('int(pow(
2.0,
3.0))', false);
192 pushTest('int(exp(
3.0))', false);
193 pushTest('int(exp2(
4.0))', false);
194 pushTest('int(floor(-
0.5))', false); // floor(-
0.5) = -
1.0
195 pushTest('int(
5.0 + fract(-
3.5))', false);
196 pushTest('int(mod(
2.0, -
4.0))', false); // mod(
2.0, -
4.0) =
2.0 - (-
4.0) * floor(
2.0 / -
4.0) =
2.0 +
4.0 * (-
1.0) = -
2.0
197 pushTest('int(mix(
2.0,
8.0,
0.9))', false);
198 pushTest('int(length(vec4(
3.0)))', false);
199 pushTest('int(lessThan(vec4(
2.0), vec4(
3.0)).x) *
4', false);
201 pushTest('true ?
5 :
0', false);
202 pushTest('int(false ?
0.0 :
5.0)', false);
203 pushTest('my_struct(
5,
1).field', false, 'struct my_struct { int field; int field2; };');
205 pushTest('int(-
0.9)', true); // conversion to int drops the fractional part
207 // Sequence operator returns the value of the right-most expression.
208 // Note that the sequence operator is allowed in constant expressions in ESSL
1.00,
209 // but not in ESSL
3.00, so with ESSL
3.00 failing compilation would not be required.
210 pushTest('
5,
1', true);
211 pushTest('
1,
5', false);
213 GLSLConformanceTester.runTests(tests);
216 var successfullyParsed = true;