constant-index-out-of-range.html (7878B)
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>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; 19 20 uniform float ua[4]; 21 22 $(init) 23 24 void main() { 25 float c = ua[$(constantExpression)]; 26 gl_Position = vec4(c); 27 } 28 </script> 29 <script id="FragmentArrayTemplate" type="x-shader/x-fragment"> 30 precision mediump float; 31 32 uniform float ua[4]; 33 34 $(init) 35 36 void main() { 37 float c = ua[$(constantExpression)]; 38 gl_FragColor = vec4(c); 39 } 40 </script> 41 <script id="VertexVectorTemplate" type="x-shader/x-vertex"> 42 precision mediump float; 43 44 uniform vec4 uv; 45 46 $(init) 47 48 void main() { 49 float c = uv[$(constantExpression)]; 50 gl_Position = vec4(c); 51 } 52 </script> 53 <script id="FragmentVectorTemplate" type="x-shader/x-fragment"> 54 precision mediump float; 55 56 uniform vec4 uv; 57 58 $(init) 59 60 void main() { 61 float c = uv[$(constantExpression)]; 62 gl_FragColor = vec4(c); 63 } 64 </script> 65 <script id="VertexMatrixTemplate" type="x-shader/x-vertex"> 66 precision mediump float; 67 68 uniform mat4 um; 69 70 $(init) 71 72 void main() { 73 float c = um[$(constantExpression)].x; 74 gl_Position = vec4(c); 75 } 76 </script> 77 <script id="FragmentMatrixTemplate" type="x-shader/x-fragment"> 78 precision mediump float; 79 80 uniform mat4 um; 81 82 $(init) 83 84 void main() { 85 float c = um[$(constantExpression)].x; 86 gl_FragColor = vec4(c); 87 } 88 </script> 89 </head> 90 <body onload="runTest()"> 91 <div id="description"></div> 92 <div id="console"></div> 93 <script type="application/javascript"> 94 "use strict"; 95 description(); 96 97 var wtu = WebGLTestUtils; 98 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. 102 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. 106 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. 110 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. 120 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; 128 129 var tests = []; 130 131 var pushTest = function(constantExpression, expectSuccess, opt_init) { 132 if (opt_init === undefined) { 133 opt_init = ''; 134 } 135 tests.push({ 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.") 140 }); 141 tests.push({ 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.") 146 }); 147 tests.push({ 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.") 152 }); 153 tests.push({ 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.") 158 }); 159 tests.push({ 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.") 164 }); 165 tests.push({ 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.") 170 }); 171 } 172 173 pushTest('0', true); 174 pushTest('3', true); 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); 186 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); 200 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; };'); 204 205 pushTest('int(-0.9)', true); // conversion to int drops the fractional part 206 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); 212 213 GLSLConformanceTester.runTests(tests); 214 } 215 216 var successfullyParsed = true; 217 </script> 218 </body> 219 </html>