switch-case.html (7639B)
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 switch/case corner case test</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 <script id="fshaderDeclarationInsideSwitch" type="x-shader/x-fragment">#version 300 es 21 22 precision highp float; 23 out vec4 my_FragColor; 24 25 uniform int u_zero; 26 27 void main() 28 { 29 my_FragColor = vec4(1, 0, 0, 1); 30 switch (u_zero) 31 { 32 case 0: 33 ivec2 i; 34 i = ivec2(1, 0); 35 my_FragColor = vec4(0, i[0], 0, 1); 36 } 37 } 38 </script> 39 <script id="fshaderDeclarationInsideSwitchDefault" type="x-shader/x-fragment">#version 300 es 40 41 precision highp float; 42 out vec4 my_FragColor; 43 44 uniform int u_zero; 45 46 void main() 47 { 48 my_FragColor = vec4(1, 0, 0, 1); 49 switch (u_zero) 50 { 51 default: 52 ivec2 i; 53 i = ivec2(1, 0); 54 my_FragColor = vec4(0, i[0], 0, 1); 55 } 56 } 57 </script> 58 <script id="fshaderDeclarationInsideSwitchLiteral" type="x-shader/x-fragment">#version 300 es 59 60 precision highp float; 61 out vec4 my_FragColor; 62 63 void main() 64 { 65 my_FragColor = vec4(1, 0, 0, 1); 66 switch (0) 67 { 68 case 0: 69 ivec2 i; 70 i = ivec2(1, 0); 71 my_FragColor = vec4(0, i[0], 0, 1); 72 } 73 } 74 </script> 75 <script id="fshaderDeclarationInsideSwitchLiteralDefault" type="x-shader/x-fragment">#version 300 es 76 77 precision highp float; 78 out vec4 my_FragColor; 79 80 void main() 81 { 82 my_FragColor = vec4(1, 0, 0, 1); 83 switch (0) 84 { 85 default: 86 ivec2 i; 87 i = ivec2(1, 0); 88 my_FragColor = vec4(0, i[0], 0, 1); 89 } 90 } 91 </script> 92 <script id="fshaderDeclarationInsideSwitchScope" type="x-shader/x-fragment">#version 300 es 93 94 precision highp float; 95 out vec4 my_FragColor; 96 97 uniform int u_zero; 98 99 // GLSL ES 3.10 clarifies the scoping rules that are relevant here. In section 4.2.2 it says: 100 // "The statement following a switch (...) forms a nested scope." 101 // There are no other special scoping rules with regards to switch statements. 102 103 void main() 104 { 105 my_FragColor = vec4(1, 0, 0, 1); 106 switch (u_zero) 107 { 108 case 0: 109 ivec2 i; 110 i = ivec2(1, 0); 111 default: 112 my_FragColor = vec4(0, i[0], 0, 1); 113 } 114 } 115 </script> 116 <script id="fshaderFallThroughAll" type="x-shader/x-fragment">#version 300 es 117 118 precision highp float; 119 120 out vec4 my_FragColor; 121 122 uniform int u_zero; 123 124 void main() 125 { 126 int i = 0; 127 // switch should fall through both cases. 128 switch(u_zero) 129 { 130 case 0: 131 i += 1; 132 case 1: 133 i += 2; 134 } 135 if (i == 3) 136 { 137 my_FragColor = vec4(0, 1, 0, 1); 138 } 139 else 140 { 141 my_FragColor = vec4(1, 0, 0, 1); 142 } 143 } 144 </script> 145 <script id="fshaderEmptySwitchStatement" type="x-shader/x-fragment">#version 300 es 146 147 precision highp float; 148 149 out vec4 my_FragColor; 150 151 uniform int u_zero; 152 153 void main() 154 { 155 switch(u_zero) 156 { 157 } 158 my_FragColor = vec4(0, 1, 0, 1); 159 } 160 </script> 161 <script id="fshaderLastCaseHasEmptyDeclaration" type="x-shader/x-fragment">#version 300 es 162 163 precision highp float; 164 165 out vec4 my_FragColor; 166 167 uniform int u_zero; 168 169 void main() 170 { 171 // Empty declaration should count as a statement. 172 switch(u_zero) 173 { 174 case 0: 175 int; 176 } 177 my_FragColor = vec4(0, 1, 0, 1); 178 } 179 </script> 180 <script id="fshaderLastCaseHasEmptyBlock" type="x-shader/x-fragment">#version 300 es 181 182 precision highp float; 183 184 out vec4 my_FragColor; 185 186 uniform int u_zero; 187 188 void main() 189 { 190 // Empty block should count as a statement. 191 switch(u_zero) 192 { 193 case 0: 194 {} 195 } 196 my_FragColor = vec4(0, 1, 0, 1); 197 } 198 </script> 199 <script id="fshaderLastCaseHasConstantStatement" type="x-shader/x-fragment">#version 300 es 200 201 precision highp float; 202 203 out vec4 my_FragColor; 204 205 uniform int u_zero; 206 207 void main() 208 { 209 // Empty statement should count as a statement. 210 switch(u_zero) 211 { 212 case 0: 213 0; 214 } 215 my_FragColor = vec4(0, 1, 0, 1); 216 } 217 </script> 218 <script id="fshaderLastCaseHasEmptyStatement" type="x-shader/x-fragment">#version 300 es 219 220 precision highp float; 221 222 out vec4 my_FragColor; 223 224 uniform int u_zero; 225 226 void main() 227 { 228 // Empty statement should count as a statement. 229 switch(u_zero) 230 { 231 case 0: 232 ; 233 } 234 my_FragColor = vec4(0, 1, 0, 1); 235 } 236 </script> 237 <script id="fshaderCaseInsideBlock" type="x-shader/x-fragment">#version 300 es 238 239 precision highp float; 240 241 out vec4 my_FragColor; 242 243 uniform int u_zero; 244 245 void main() 246 { 247 // Case statements must not be nested in blocks. 248 // GLSL ES 3.00 spec is a bit vague on this but GLSL ES 3.10 section 6.2 is clearer. 249 switch(u_zero) 250 { 251 case 1: 252 { 253 case 0: 254 my_FragColor = vec4(1, 0, 0, 1); 255 } 256 } 257 my_FragColor = vec4(0, 1, 0, 1); 258 } 259 </script> 260 <script type="application/javascript"> 261 "use strict"; 262 description(); 263 264 // Covers bugs: 265 // http://anglebug.com/2177 266 // http://anglebug.com/2178 267 // http://anglebug.com/2179 268 269 GLSLConformanceTester.runTests([ 270 { 271 fShaderId: 'fshaderDeclarationInsideSwitch', 272 fShaderSuccess: true, 273 linkSuccess: true, 274 passMsg: 'Declaration inside switch should work.', 275 render: true 276 }, 277 { 278 fShaderId: 'fshaderDeclarationInsideSwitchDefault', 279 fShaderSuccess: true, 280 linkSuccess: true, 281 passMsg: 'Declaration inside switch default case should work.', 282 render: true 283 }, 284 { 285 fShaderId: 'fshaderDeclarationInsideSwitchLiteral', 286 fShaderSuccess: true, 287 linkSuccess: true, 288 passMsg: 'Declaration inside switch with literal value should work.', 289 render: true 290 }, 291 { 292 fShaderId: 'fshaderDeclarationInsideSwitchLiteralDefault', 293 fShaderSuccess: true, 294 linkSuccess: true, 295 passMsg: 'Declaration inside switch with literal value and default case should work.', 296 render: true 297 }, 298 { 299 fShaderId: 'fshaderDeclarationInsideSwitchScope', 300 fShaderSuccess: true, 301 linkSuccess: true, 302 passMsg: 'Declaration inside switch should be scoped until the end of the switch statement.', 303 render: true 304 }, 305 { 306 fShaderId: 'fshaderFallThroughAll', 307 fShaderSuccess: true, 308 linkSuccess: true, 309 passMsg: 'Falling through all cases in switch/case should work.', 310 render: true 311 }, 312 { 313 fShaderId: 'fshaderEmptySwitchStatement', 314 fShaderSuccess: true, 315 linkSuccess: true, 316 passMsg: 'Empty switch statements are valid.' 317 }, 318 { 319 fShaderId: 'fshaderLastCaseHasEmptyDeclaration', 320 fShaderSuccess: true, 321 linkSuccess: true, 322 passMsg: 'Empty declaration should count as a statement for the purposes of switch statement validation.' 323 }, 324 { 325 fShaderId: 'fshaderLastCaseHasEmptyBlock', 326 fShaderSuccess: true, 327 linkSuccess: true, 328 passMsg: 'Empty block should count as a statement for the purposes of switch statement validation.' 329 }, 330 { 331 fShaderId: 'fshaderLastCaseHasConstantStatement', 332 fShaderSuccess: true, 333 linkSuccess: true, 334 passMsg: 'Constant statement should count as a statement for the purposes of switch statement validation.' 335 }, 336 { 337 fShaderId: 'fshaderLastCaseHasEmptyStatement', 338 fShaderSuccess: true, 339 linkSuccess: true, 340 passMsg: 'Empty statement should count as a statement for the purposes of switch statement validation.' 341 }, 342 { 343 fShaderId: 'fshaderCaseInsideBlock', 344 fShaderSuccess: false, 345 passMsg: 'Case statements must not be nested inside blocks.' 346 } 347 ], 2); 348 </script> 349 </body> 350 </html>