const-variable-initialization.html (7335B)
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>All valid constant expressions should be allowed in the initialization of const variables</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="VertexTemplate" type="x-shader/x-vertex"> 18 precision mediump float; 19 20 $(init) 21 22 void main() { 23 const $(constType) c = $(constantExpression); 24 gl_Position = vec4(float(c$(constTypeToScalar))); 25 } 26 </script> 27 <script id="FragmentTemplate" type="x-shader/x-fragment"> 28 precision mediump float; 29 30 $(init) 31 32 void main() { 33 const $(constType) c = $(constantExpression); 34 gl_FragColor = vec4(float(c$(constTypeToScalar))); 35 } 36 </script> 37 </head> 38 <body onload="runTest()"> 39 <div id="description"></div> 40 <div id="console"></div> 41 <script type="application/javascript"> 42 "use strict"; 43 description(); 44 45 var wtu = WebGLTestUtils; 46 47 // ESSL 1.00 spec section 4.3.2. 48 // Initializers for const declarations must be a constant expression. 49 50 // ESSL 1.00 spec section 5.10. 51 // A constant expression is one of 52 // * a literal value (e.g., 5 or true) 53 // * a global or local variable qualified as const excluding function parameters 54 // * an expression formed by an operator on operands that are constant expressions, including getting 55 // an element of a constant vector or a constant matrix, or a field of a constant structure 56 // * a constructor whose arguments are all constant expressions 57 // * a built-in function call whose arguments are all constant expressions, with the exception of the 58 // texture lookup functions. 59 60 var binaryOpsGenTypeRValuesToGenType = [ 61 '+', 62 '-', 63 '*', 64 '/' 65 ]; 66 67 var binaryOpsScalarsToBool = [ 68 '<', 69 '>', 70 '<=', 71 '>=' 72 ]; 73 74 var binaryOpsRValuesToBool = [ 75 '==', 76 '!=' 77 ]; 78 79 var binaryOpsBoolsToBool = [ 80 '&&', 81 '^^', 82 '||' 83 ]; 84 85 var builtInsGenTypeToGenType = [ 86 'radians', 87 'degrees', 88 'sin', 89 'cos', 90 'tan', 91 'asin', 92 'acos', 93 'atan', 94 'exp', 95 'log', 96 'exp2', 97 'log2', 98 'sqrt', 99 'inversesqrt', 100 'abs', 101 'sign', 102 'floor', 103 'ceil', 104 'fract' 105 ]; 106 107 var builtIns2VecToBvec = [ 108 'lessThan', 109 'lessThanEqual', 110 'greaterThan', 111 'greaterThanEqual', 112 'equal', 113 'notEqual' 114 ]; 115 116 var builtIns2GenTypeToGenType = [ 117 'atan', 118 'pow', 119 'mod', 120 'min', 121 'max', 122 'step' 123 ]; 124 125 var runTest = function() { 126 var vsTemplate = document.getElementById('VertexTemplate').text; 127 var fsTemplate = document.getElementById('FragmentTemplate').text; 128 129 var tests = []; 130 var i; 131 var op; 132 var builtIn; 133 134 var pushTest = function(constType, constantExpression, expectSuccess, opt_init) { 135 if (opt_init === undefined) { 136 opt_init = ''; 137 } 138 var constTypeToScalar = ''; 139 if (constType.substring(0, 3) == 'vec' || constType.substring(1, 4) == 'vec') { 140 constTypeToScalar = '.x'; 141 } else if (constType.substring(0, 3) == 'mat') { 142 constTypeToScalar = '[0].x'; 143 } else if (constType == 'my_struct') { 144 constTypeToScalar = '.field'; 145 } 146 var vs = wtu.replaceParams(vsTemplate, {constType: constType, constantExpression: constantExpression, constTypeToScalar: constTypeToScalar, init: opt_init}); 147 var fs = wtu.replaceParams(fsTemplate, {constType: constType, constantExpression: constantExpression, constTypeToScalar: constTypeToScalar, init: opt_init}); 148 tests.push({ 149 vShaderSource: vs, 150 vShaderSuccess: expectSuccess, 151 linkSuccess: expectSuccess, 152 passMsg: "Assigning " + constantExpression + " to a const in a vertex shader should " + (expectSuccess ? "compile." : "fail compilation.") 153 }); 154 tests.push({ 155 fShaderSource: fs, 156 fShaderSuccess: expectSuccess, 157 linkSuccess: expectSuccess, 158 passMsg: "Assigning " + constantExpression + " to a const in a fragment shader should " + (expectSuccess ? "compile." : "fail compilation.") 159 }); 160 } 161 162 // Handle some one of a kind cases first 163 pushTest('float', 'vec4(0.5).x', true); 164 pushTest('float', 'vec4(0.5)[0]', true); 165 pushTest('float', 'true ? 0.5 : 0.2', true); 166 pushTest('my_struct', 'my_struct(0.5, 0.2)', true, 'struct my_struct { float field; float field2; };'); 167 pushTest('float', '(0.2, 0.5)', true); 168 169 pushTest('float', 'clamp(0.2, 0.3, 0.4)', true); 170 pushTest('float', 'mix(0.2, 0.3, 0.4)', true); 171 pushTest('float', 'smoothstep(0.2, 0.3, 0.4)', true); 172 pushTest('float', 'length(vec4(0.5))', true); 173 pushTest('float', 'distance(vec4(0.5), vec4(0.2))', true); 174 pushTest('float', 'dot(vec4(0.5), vec4(0.2))', true); 175 pushTest('vec3', 'cross(vec3(0.5), vec3(0.2))', true); 176 pushTest('vec4', 'normalize(vec4(0.5))', true); 177 pushTest('vec4', 'faceforward(vec4(0.2), vec4(0.3), vec4(0.4))', true); 178 pushTest('vec4', 'reflect(vec4(0.2), vec4(0.5))', true); 179 pushTest('vec4', 'refract(vec4(0.2), vec4(0.3), 0.4)', true); 180 pushTest('mat4', 'matrixCompMult(mat4(0.2), mat4(0.5))', true); 181 182 // Handle built-in constructors 183 for (i = 2; i <= 4; ++i) { 184 var vecType = 'vec' + i; 185 pushTest(vecType, vecType + '(0.5)', true); 186 pushTest('i' + vecType, 'i' + vecType + '(1)', true); 187 pushTest('b' + vecType, 'b' + vecType + '(true)', true); 188 pushTest('mat' + i, 'mat' + i + '(0.5)', true); 189 } 190 191 // Handle ops 192 for (i = 0; i < binaryOpsGenTypeRValuesToGenType.length; ++i) { 193 var op = binaryOpsGenTypeRValuesToGenType[i]; 194 pushTest('float', '0.2 ' + op + ' 0.5', true); 195 pushTest('vec4', 'vec4(0.2) ' + op + ' vec4(0.5)', true); 196 pushTest('mat4', 'mat4(0.2) ' + op + ' mat4(0.5)', true); 197 } 198 199 for (i = 0; i < binaryOpsScalarsToBool.length; ++i) { 200 var op = binaryOpsScalarsToBool[i]; 201 pushTest('bool', '0.2 ' + op + ' 0.5', true); 202 } 203 204 for (i = 0; i < binaryOpsRValuesToBool.length; ++i) { 205 var op = binaryOpsRValuesToBool[i]; 206 pushTest('bool', '0.2 ' + op + ' 0.5', true); 207 pushTest('bool', 'vec4(0.2) ' + op + ' vec4(0.5)', true); 208 } 209 210 for (i = 0; i < binaryOpsBoolsToBool.length; ++i) { 211 var op = binaryOpsBoolsToBool[i]; 212 pushTest('bool', 'false ' + op + ' true', true); 213 } 214 215 // Handle allowed built-ins 216 for (i = 0; i < builtInsGenTypeToGenType.length; ++i) { 217 builtIn = builtInsGenTypeToGenType[i]; 218 pushTest('float', builtIn + '(0.5)', true); 219 pushTest('vec4', builtIn + '(vec4(0.5))', true); 220 } 221 222 for (i = 0; i < builtIns2VecToBvec.length; ++i) { 223 builtIn = builtIns2VecToBvec[i]; 224 pushTest('bvec4', builtIn + '(vec4(0.2), vec4(0.5))', true); 225 } 226 227 for (i = 0; i < builtIns2GenTypeToGenType.length; ++i) { 228 builtIn = builtIns2GenTypeToGenType[i]; 229 pushTest('float', builtIn + '(0.2, 0.5)', true); 230 pushTest('vec4', builtIn + '(vec4(0.2), vec4(0.5))', true); 231 } 232 233 // Include some expressions with a constant variable reference 234 pushTest('float', 'cc', true, 'const float cc = 0.5;'); 235 pushTest('float', 'cc + cc2', true, 'const float cc = 0.5; const float cc2 = 0.2;'); 236 pushTest('float', 'sqrt(cc)', true, 'const float cc = 0.5;'); 237 238 GLSLConformanceTester.runTests(tests); 239 } 240 241 var successfullyParsed = true; 242 </script> 243 </body> 244 </html>