summaryrefslogtreecommitdiffstats
path: root/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fShaderTextureFunctionTests.js
blob: b6386c96edfdaed6d317f96cf492f569a911fc1a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES Utilities
 * ------------------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

'use strict';
goog.provide('functional.gles3.es3fShaderTextureFunctionTests');
goog.require('framework.delibs.debase.deMath');
goog.require('framework.opengl.gluTextureUtil');
goog.require('framework.opengl.gluTexture');
goog.require('framework.opengl.gluShaderProgram');
goog.require('framework.opengl.gluShaderUtil');
goog.require('framework.common.tcuMatrix');
goog.require('framework.common.tcuSurface');
goog.require('framework.common.tcuTestCase');
goog.require('framework.common.tcuTexture');
goog.require('framework.common.tcuTextureUtil');
goog.require('modules.shared.glsShaderRenderCase');

goog.scope(function() {
    var es3fShaderTextureFunctionTests = functional.gles3.es3fShaderTextureFunctionTests;
    var deMath = framework.delibs.debase.deMath;
    var tcuMatrix = framework.common.tcuMatrix;
    var tcuTestCase = framework.common.tcuTestCase;
    var tcuSurface = framework.common.tcuSurface;
    var tcuTexture = framework.common.tcuTexture;
    var tcuTextureUtil = framework.common.tcuTextureUtil;
    var gluTextureUtil = framework.opengl.gluTextureUtil;
    var gluTexture = framework.opengl.gluTexture;
    var gluShaderProgram = framework.opengl.gluShaderProgram;
    var gluShaderUtil = framework.opengl.gluShaderUtil;
    var glsShaderRenderCase = modules.shared.glsShaderRenderCase;

    let canvasWH = 256;
    if (tcuTestCase.isQuickMode()) {
        canvasWH = 32;
    }

    /**
     * @enum
     */
    es3fShaderTextureFunctionTests.TexFunction = {
        TEXTURE: 0, //!< texture(), textureOffset()
        TEXTUREPROJ: 1, //!< textureProj(), textureProjOffset()
        TEXTUREPROJ3: 2, //!< textureProj(sampler2D, vec3)
        TEXTURELOD: 3, // ...
        TEXTUREPROJLOD: 4,
        TEXTUREPROJLOD3: 5, //!< textureProjLod(sampler2D, vec3)
        TEXTUREGRAD: 6,
        TEXTUREPROJGRAD: 7,
        TEXTUREPROJGRAD3: 8, //!< textureProjGrad(sampler2D, vec3)
        TEXELFETCH: 9
    };

    /**
     * @param {gluShaderProgram.shaderType} shaderType
     * @param {es3fShaderTextureFunctionTests.TexFunction} function_
     * @return {boolean}
     */
    es3fShaderTextureFunctionTests.functionHasAutoLod = function(shaderType, function_) {
        return shaderType === gluShaderProgram.shaderType.FRAGMENT &&
            (function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTURE ||
            function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ ||
            function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3);
    };

    /**
     * @param {es3fShaderTextureFunctionTests.TexFunction} function_
     * @return {boolean}
     */
    es3fShaderTextureFunctionTests.functionHasProj = function(function_) {
        return function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ ||
           function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3 ||
           function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD ||
           function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD ||
           function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD3 ||
           function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD3;
    };

    /**
     * @param {es3fShaderTextureFunctionTests.TexFunction} function_
     * @return {boolean}
     */
    es3fShaderTextureFunctionTests.functionHasGrad = function(function_) {
        return function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD ||
            function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD ||
             function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD3;
    };

    /**
     * @param {es3fShaderTextureFunctionTests.TexFunction} function_
     * @return {boolean}
     */
    es3fShaderTextureFunctionTests.functionHasLod = function(function_) {
        return function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD ||
               function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD ||
               function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD3 ||
               function_ === es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH;
    };

    /**
     * @struct
     * @constructor
     * @param {es3fShaderTextureFunctionTests.TexFunction} func
     * @param {Array<number>} minCoord
     * @param {Array<number>} maxCoord
     * @param {boolean} useBias
     * @param {number} minLodBias
     * @param {number} maxLodBias
     * @param {Array<number>} minDX For *Grad* functions
     * @param {Array<number>} maxDX For *Grad* functions
     * @param {Array<number>} minDY For *Grad* functions
     * @param {Array<number>} maxDY For *Grad* functions
     * @param {boolean} useOffset
     * @param {Array<number>} offset
     */
    es3fShaderTextureFunctionTests.TextureLookupSpec = function(func, minCoord, maxCoord, useBias, minLodBias, maxLodBias, minDX, maxDX, minDY, maxDY, useOffset, offset) {
        /** @type {es3fShaderTextureFunctionTests.TexFunction} */ this.func = func;
        /** @type {Array<number>} */ this.minCoord = minCoord;
        /** @type {Array<number>} */ this.maxCoord = maxCoord;
        // Bias
        /** @type {boolean} */ this.useBias = useBias;
        // Bias or Lod for *Lod* functions
        /** @type {number} */ this.minLodBias = minLodBias;
        /** @type {number} */ this.maxLodBias = maxLodBias;
        // For *Grad* functions
        /** @type {Array<number>} */ this.minDX = minDX;
        /** @type {Array<number>} */ this.maxDX = maxDX;
        /** @type {Array<number>} */ this.minDY = minDY;
        /** @type {Array<number>} */ this.maxDY = maxDY;
        /** @type {boolean} */ this.useOffset = useOffset;
        /** @type {Array<number>} */ this.offset = offset;
    };

    /**
     * @enum
     */
    es3fShaderTextureFunctionTests.TextureType = {
        TEXTURETYPE_2D: 0,
        TEXTURETYPE_CUBE_MAP: 1,
        TEXTURETYPE_2D_ARRAY: 2,
        TEXTURETYPE_3D: 3
    };

    /**
     * @struct
     * @constructor
     * @param {?es3fShaderTextureFunctionTests.TextureType} type
     * @param {number} format
     * @param {number} width
     * @param {number} height
     * @param {number} depth
     * @param {number} numLevels
     * @param {?tcuTexture.Sampler} sampler
     */
    es3fShaderTextureFunctionTests.TextureSpec = function(type, format, width, height, depth, numLevels, sampler) {
        /** @type {?es3fShaderTextureFunctionTests.TextureType} */ this.type = type; //!< Texture type (2D, cubemap, ...)
        /** @type {number} */ this.format = format; //!< Internal format.
        /** @type {number} */ this.width = width;
        /** @type {number} */ this.height = height;
        /** @type {number} */ this.depth = depth;
        /** @type {number} */ this.numLevels = numLevels;
        /** @type {?tcuTexture.Sampler} */ this.sampler = sampler;
    };

    /**
     * @struct
     * @constructor
     */
    es3fShaderTextureFunctionTests.TexLookupParams = function() {
        /** @type {number} */ this.lod = 0;
        /** @type {Array<number>} */ this.offset = [0, 0, 0];
        /** @type {Array<number>} */ this.scale = [1.0, 1.0, 1.0, 1.0];
        /** @type {Array<number>} */ this.bias = [0.0, 0.0, 0.0, 0.0];
    };

    /**
     * @enum
     */
    es3fShaderTextureFunctionTests.LodMode = {
        EXACT: 0,
        MIN_BOUND: 1,
        MAX_BOUND: 2
    };

    /** @const {es3fShaderTextureFunctionTests.LodMode} */ es3fShaderTextureFunctionTests.DEFAULT_LOD_MODE = es3fShaderTextureFunctionTests.LodMode.EXACT;

    /**
     * @param {number} dudx
     * @param {number} dvdx
     * @param {number} dudy
     * @param {number} dvdy
     * @return {number}
     */
    es3fShaderTextureFunctionTests.computeLodFromDerivates_UV = function(dudx, dvdx, dudy, dvdy) {
        /** @type {es3fShaderTextureFunctionTests.LodMode} */ var mode = es3fShaderTextureFunctionTests.DEFAULT_LOD_MODE;
        /** @type {number} */ var p;

        switch (mode) {
            case es3fShaderTextureFunctionTests.LodMode.EXACT:
                p = Math.max(Math.sqrt(dudx * dudx + dvdx * dvdx), Math.sqrt(dudy * dudy + dvdy * dvdy));
                break;

            case es3fShaderTextureFunctionTests.LodMode.MIN_BOUND:
            case es3fShaderTextureFunctionTests.LodMode.MAX_BOUND:
                /** @type {number} */ var mu = Math.max(Math.abs(dudx), Math.abs(dudy));
                /** @type {number} */ var mv = Math.max(Math.abs(dvdx), Math.abs(dvdy));

                p = mode === es3fShaderTextureFunctionTests.LodMode.MIN_BOUND ? Math.max(mu, mv) : mu + mv;
                break;

            default:
                throw new Error('LOD_MODE not supported.');
        }

        return Math.log2(p);
    };

    /**
     * @param {number} dudx
     * @param {number} dvdx
     * @param {number} dwdx
     * @param {number} dudy
     * @param {number} dvdy
     * @param {number} dwdy
     * @return {number}
     */
    es3fShaderTextureFunctionTests.computeLodFromDerivates_UVW = function(dudx, dvdx, dwdx, dudy, dvdy, dwdy) {
        /** @type {es3fShaderTextureFunctionTests.LodMode} */ var mode = es3fShaderTextureFunctionTests.DEFAULT_LOD_MODE;
        /** @type {number} */ var p;

        switch (mode) {
            case es3fShaderTextureFunctionTests.LodMode.EXACT:
                p = Math.max(Math.sqrt(dudx * dudx + dvdx * dvdx + dwdx * dwdx), Math.sqrt(dudy * dudy + dvdy * dvdy + dwdy * dwdy));
                break;

            case es3fShaderTextureFunctionTests.LodMode.MIN_BOUND:
            case es3fShaderTextureFunctionTests.LodMode.MAX_BOUND:
                /** @type {number} */ var mu = Math.max(Math.abs(dudx), Math.abs(dudy));
                /** @type {number} */ var mv = Math.max(Math.abs(dvdx), Math.abs(dvdy));
                /** @type {number} */ var mw = Math.max(Math.abs(dwdx), Math.abs(dwdy));

                p = mode === es3fShaderTextureFunctionTests.LodMode.MIN_BOUND ? Math.max(mu, mv, mw) : (mu + mv + mw);
                break;

            default:
                throw new Error('LOD_MODE not supported.');
        }

        return Math.log2(p);
    };

    /**
     * [dag] Wrapper function for computeLodFromDerivates_UV or computeLodFromDerivates_UVW
     * @param {number} dudx
     * @param {number} dvdx
     * @param {number} dwdxOrdudy
     * @param {number} dudyOrdvdy
     * @param {number=} dvdy
     * @param {number=} dwdy
     * @return {number}
     */
    es3fShaderTextureFunctionTests.computeLodFromDerivates = function(dudx, dvdx, dwdxOrdudy, dudyOrdvdy, dvdy, dwdy) {
        if (arguments.length === 4)
            return es3fShaderTextureFunctionTests.computeLodFromDerivates_UV(dudx, dvdx, dwdxOrdudy, dudyOrdvdy);
        else
            return es3fShaderTextureFunctionTests.computeLodFromDerivates_UVW(dudx, dvdx, dwdxOrdudy, dudyOrdvdy, /** @type {number} */ (dvdy), /** @type {number} */ (dwdy));
    };

       /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @return {number}
     */
    es3fShaderTextureFunctionTests.computeLodFromGrad2D = function(c) {
        /** @type {number} */ var w = c.textures[0].tex2D.getWidth();
        /** @type {number} */ var h = c.textures[0].tex2D.getHeight();
        return es3fShaderTextureFunctionTests.computeLodFromDerivates(c.in_[1][0] * w, c.in_[1][1] * h, c.in_[2][0] * w, c.in_[2][1] * h);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @return {number}
     */
    es3fShaderTextureFunctionTests.computeLodFromGrad2DArray = function(c) {
        /** @type {number} */ var w = c.textures[0].tex2DArray.getWidth();
        /** @type {number} */ var h = c.textures[0].tex2DArray.getHeight();
        return es3fShaderTextureFunctionTests.computeLodFromDerivates(c.in_[1][0] * w, c.in_[1][1] * h, c.in_[2][0] * w, c.in_[2][1] * h);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @return {number}
     */
    es3fShaderTextureFunctionTests.computeLodFromGrad3D = function(c) {
        /** @type {number} */ var w = c.textures[0].tex3D.getWidth();
        /** @type {number} */ var h = c.textures[0].tex3D.getHeight();
        /** @type {number} */ var d = c.textures[0].tex3D.getDepth();
        return es3fShaderTextureFunctionTests.computeLodFromDerivates(c.in_[1][0] * w, c.in_[1][1] * h, c.in_[1][2] * d, c.in_[2][0] * w, c.in_[2][1] * h, c.in_[2][2] * d);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @return {number}
     */
    es3fShaderTextureFunctionTests.computeLodFromGradCube = function(c) {
        // \note Major axis is always -Z or +Z
        /** @type {number} */ var m = Math.abs(c.in_[0][2]);
        /** @type {number} */ var d = c.textures[0].texCube.getSize();
        /** @type {number} */ var s = d / (2.0 * m);
        /** @type {number} */ var t = d / (2.0 * m);
        return es3fShaderTextureFunctionTests.computeLodFromDerivates(c.in_[1][0] * s, c.in_[1][1] * t, c.in_[2][0] * s, c.in_[2][1] * t);
    };

    /** @typedef {function(glsShaderRenderCase.ShaderEvalContext, es3fShaderTextureFunctionTests.TexLookupParams)} */ es3fShaderTextureFunctionTests.TexEvalFunc;

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {number} s
     * @param {number} t
     * @param {number} lod
     * @return {Array<number>}
     */
    es3fShaderTextureFunctionTests.texture2D = function(c, s, t, lod) {
        return c.textures[0].tex2D.getView().sample(c.textures[0].sampler, [s, t], lod);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {number} s
     * @param {number} t
     * @param {number} r
     * @param {number} lod
     * @return {Array<number>}
     */
    es3fShaderTextureFunctionTests.textureCube = function(c, s, t, r, lod) {
        return c.textures[0].texCube.getView().sample(c.textures[0].sampler, [s, t, r], lod);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {number} s
     * @param {number} t
     * @param {number} r
     * @param {number} lod
     * @return {Array<number>}
     */
    es3fShaderTextureFunctionTests.texture2DArray = function(c, s, t, r, lod) {
        return c.textures[0].tex2DArray.getView().sample(c.textures[0].sampler, [s, t, r], lod);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {number} s
     * @param {number} t
     * @param {number} r
     * @param {number} lod
     * @return {Array<number>}
     */
    es3fShaderTextureFunctionTests.texture3D = function(c, s, t, r, lod) {
        return c.textures[0].tex3D.getView().sample(c.textures[0].sampler, [s, t, r], lod);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {number} ref
     * @param {number} s
     * @param {number} t
     * @param {number} lod
     * @return {number}
     */
    es3fShaderTextureFunctionTests.texture2DShadow = function(c, ref, s, t, lod) {
        return c.textures[0].tex2D.getView().sampleCompare(c.textures[0].sampler, ref, [s, t], lod);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {number} ref
     * @param {number} s
     * @param {number} t
     * @param {number} r
     * @param {number} lod
     * @return {number}
     */
    es3fShaderTextureFunctionTests.textureCubeShadow = function(c, ref, s, t, r, lod) {
        return c.textures[0].texCube.getView().sampleCompare(c.textures[0].sampler, ref, [s, t, r], lod);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {number} ref
     * @param {number} s
     * @param {number} t
     * @param {number} r
     * @param {number} lod
     * @return {number}
     */
    es3fShaderTextureFunctionTests.texture2DArrayShadow = function(c, ref, s, t, r, lod) {
        return c.textures[0].tex2DArray.getView().sampleCompare(c.textures[0].sampler, ref, [s, t, r], lod);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {number} s
     * @param {number} t
     * @param {number} lod
     * @param {Array<number>} offset
     * @return {Array<number>}
     */
    es3fShaderTextureFunctionTests.texture2DOffset = function(c, s, t, lod, offset) {
        return c.textures[0].tex2D.getView().sampleOffset(c.textures[0].sampler, [s, t], lod, offset);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {number} s
     * @param {number} t
     * @param {number} r
     * @param {number} lod
     * @param {Array<number>} offset
     * @return {Array<number>}
     */
    es3fShaderTextureFunctionTests.texture2DArrayOffset = function(c, s, t, r, lod, offset) {
        return c.textures[0].tex2DArray.getView().sampleOffset(c.textures[0].sampler, [s, t, r], lod, offset);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {number} s
     * @param {number} t
     * @param {number} r
     * @param {number} lod
     * @param {Array<number>} offset
     * @return {Array<number>}
     */
    es3fShaderTextureFunctionTests.texture3DOffset = function(c, s, t, r, lod, offset) {
        return c.textures[0].tex3D.getView().sampleOffset(c.textures[0].sampler, [s, t, r], lod, offset);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {number} ref
     * @param {number} s
     * @param {number} t
     * @param {number} lod
     * @param {Array<number>} offset
     * @return {number}
     */
    es3fShaderTextureFunctionTests.texture2DShadowOffset = function(c, ref, s, t, lod, offset) {
        return c.textures[0].tex2D.getView().sampleCompareOffset(c.textures[0].sampler, ref, [s, t], lod, offset);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {number} ref
     * @param {number} s
     * @param {number} t
     * @param {number} r
     * @param {number} lod
     * @param {Array<number>} offset
     * @return {number}
     */
    es3fShaderTextureFunctionTests.texture2DArrayShadowOffset = function(c, ref, s, t, r, lod, offset) {
        return c.textures[0].tex2DArray.getView().sampleCompareOffset(c.textures[0].sampler, ref, [s, t, r], lod, offset);
    };

    // Eval functions.
    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2D = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2D(c, c.in_[0][0], c.in_[0][1], p.lod), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTextureCube = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.textureCube(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], p.lod), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DArray = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DArray(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], p.lod), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture3D = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3D(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], p.lod), p.scale), p.bias);
    };


    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DBias = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2D(c, c.in_[0][0], c.in_[0][1], p.lod+c.in_[1][0]), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTextureCubeBias = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.textureCube(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], p.lod+c.in_[1][0]), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DArrayBias = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DArray(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], p.lod+c.in_[1][0]), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture3DBias = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3D(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], p.lod+c.in_[1][0]), p.scale), p.bias);
    };


    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DProj3 = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2D(c, c.in_[0][0]/c.in_[0][2], c.in_[0][1]/c.in_[0][2], p.lod), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DProj3Bias = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2D(c, c.in_[0][0]/c.in_[0][2], c.in_[0][1]/c.in_[0][2], p.lod+c.in_[1][0]), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DProj = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2D(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], p.lod), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DProjBias = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2D(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], p.lod+c.in_[1][0]), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture3DProj = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3D(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], c.in_[0][2]/c.in_[0][3], p.lod), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture3DProjBias = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3D(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], c.in_[0][2]/c.in_[0][3], p.lod+c.in_[1][0]), p.scale), p.bias);
    };


    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DLod = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2D(c, c.in_[0][0], c.in_[0][1], c.in_[1][0]), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTextureCubeLod = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.textureCube(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], c.in_[1][0]), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DArrayLod = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DArray(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], c.in_[1][0]), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture3DLod = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3D(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], c.in_[1][0]), p.scale), p.bias);
    };


    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DProjLod3 = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2D(c, c.in_[0][0]/c.in_[0][2], c.in_[0][1]/c.in_[0][2], c.in_[1][0]), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DProjLod = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2D(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], c.in_[1][0]), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture3DProjLod = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3D(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], c.in_[0][2]/c.in_[0][3], c.in_[1][0]), p.scale), p.bias);
    };

    // Offset variants

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DOffset = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DOffset(c, c.in_[0][0], c.in_[0][1], p.lod, deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DArrayOffset = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DArrayOffset(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], p.lod, deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture3DOffset = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3DOffset(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], p.lod, p.offset), p.scale), p.bias);
    };


    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DOffsetBias = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DOffset(c, c.in_[0][0], c.in_[0][1], p.lod+c.in_[1][0], deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DArrayOffsetBias = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DArrayOffset(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], p.lod+c.in_[1][0], deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture3DOffsetBias = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3DOffset(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], p.lod+c.in_[1][0], p.offset), p.scale), p.bias);
    };


    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DLodOffset = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DOffset(c, c.in_[0][0], c.in_[0][1], c.in_[1][0], deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DArrayLodOffset = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DArrayOffset(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], c.in_[1][0], deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture3DLodOffset = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3DOffset(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], c.in_[1][0], p.offset), p.scale), p.bias);
    };


    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DProj3Offset = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DOffset(c, c.in_[0][0]/c.in_[0][2], c.in_[0][1]/c.in_[0][2], p.lod, deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DProj3OffsetBias = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DOffset(c, c.in_[0][0]/c.in_[0][2], c.in_[0][1]/c.in_[0][2], p.lod+c.in_[1][0], deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DProjOffset = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DOffset(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], p.lod, deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DProjOffsetBias = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DOffset(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], p.lod+c.in_[1][0], deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture3DProjOffset = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3DOffset(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], c.in_[0][2]/c.in_[0][3], p.lod, p.offset), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture3DProjOffsetBias = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3DOffset(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], c.in_[0][2]/c.in_[0][3], p.lod+c.in_[1][0], p.offset), p.scale), p.bias);
    };


    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DProjLod3Offset = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DOffset(c, c.in_[0][0]/c.in_[0][2], c.in_[0][1]/c.in_[0][2], c.in_[1][0], deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DProjLodOffset = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DOffset(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], c.in_[1][0], deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture3DProjLodOffset = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3DOffset(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], c.in_[0][2]/c.in_[0][3], c.in_[1][0], p.offset), p.scale), p.bias);
    };

    // Shadow variants

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DShadow = function(c, p) {
        c.color[0] = es3fShaderTextureFunctionTests.texture2DShadow(c, c.in_[0][2], c.in_[0][0], c.in_[0][1], p.lod);
    };
    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DShadowBias = function(c, p) {
        c.color[0] = es3fShaderTextureFunctionTests.texture2DShadow(c, c.in_[0][2], c.in_[0][0], c.in_[0][1], p.lod+c.in_[1][0]);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTextureCubeShadow = function(c, p) {
        c.color[0] = es3fShaderTextureFunctionTests.textureCubeShadow(c, c.in_[0][3], c.in_[0][0], c.in_[0][1], c.in_[0][2], p.lod);
    };
    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTextureCubeShadowBias = function(c, p) {
        c.color[0] = es3fShaderTextureFunctionTests.textureCubeShadow(c, c.in_[0][3], c.in_[0][0], c.in_[0][1], c.in_[0][2], p.lod+c.in_[1][0]);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DArrayShadow = function(c, p) {
        c.color[0] = es3fShaderTextureFunctionTests.texture2DArrayShadow(c, c.in_[0][3], c.in_[0][0], c.in_[0][1], c.in_[0][2], p.lod);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DShadowLod = function(c, p) {
        c.color[0] = es3fShaderTextureFunctionTests.texture2DShadow(c, c.in_[0][2], c.in_[0][0], c.in_[0][1], c.in_[1][0]);
    };
    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DShadowLodOffset = function(c, p) {
        c.color[0] = es3fShaderTextureFunctionTests.texture2DShadowOffset(c, c.in_[0][2], c.in_[0][0], c.in_[0][1], c.in_[1][0], deMath.swizzle(p.offset, [0,1]));
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DShadowProj = function(c, p) {
        c.color[0] = es3fShaderTextureFunctionTests.texture2DShadow(c, c.in_[0][2]/c.in_[0][3], c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], p.lod);
    };
    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DShadowProjBias = function(c, p) {
        c.color[0] = es3fShaderTextureFunctionTests.texture2DShadow(c, c.in_[0][2]/c.in_[0][3], c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], p.lod+c.in_[1][0]);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DShadowProjLod = function(c, p) {
        c.color[0] = es3fShaderTextureFunctionTests.texture2DShadow(c, c.in_[0][2]/c.in_[0][3], c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], c.in_[1][0]);
    };
    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DShadowProjLodOffset = function(c, p) {
        c.color[0] = es3fShaderTextureFunctionTests.texture2DShadowOffset(c, c.in_[0][2]/c.in_[0][3], c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], c.in_[1][0], deMath.swizzle(p.offset, [0,1]));
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DShadowOffset = function(c, p) {
        c.color[0] = es3fShaderTextureFunctionTests.texture2DShadowOffset(c, c.in_[0][2], c.in_[0][0], c.in_[0][1], p.lod, deMath.swizzle(p.offset, [0,1]));
    };
    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DShadowOffsetBias = function(c, p) {
        c.color[0] = es3fShaderTextureFunctionTests.texture2DShadowOffset(c, c.in_[0][2], c.in_[0][0], c.in_[0][1], p.lod+c.in_[1][0], deMath.swizzle(p.offset, [0,1]));
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DShadowProjOffset = function(c, p) {
        c.color[0] = es3fShaderTextureFunctionTests.texture2DShadowOffset(c, c.in_[0][2]/c.in_[0][3], c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], p.lod, deMath.swizzle(p.offset, [0,1]));
    };
    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DShadowProjOffsetBias = function(c, p) {
        c.color[0] = es3fShaderTextureFunctionTests.texture2DShadowOffset(c, c.in_[0][2]/c.in_[0][3], c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], p.lod+c.in_[1][0], deMath.swizzle(p.offset, [0,1]));
    };

    // Gradient variarts

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DGrad = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2D(c, c.in_[0][0], c.in_[0][1], es3fShaderTextureFunctionTests.computeLodFromGrad2D(c)), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTextureCubeGrad = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.textureCube(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], es3fShaderTextureFunctionTests.computeLodFromGradCube(c)), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DArrayGrad = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DArray(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], es3fShaderTextureFunctionTests.computeLodFromGrad2DArray(c)), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture3DGrad = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3D(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], es3fShaderTextureFunctionTests.computeLodFromGrad3D(c)), p.scale), p.bias);
    };


    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DShadowGrad = function(c, p) {
        c.color[0] = es3fShaderTextureFunctionTests.texture2DShadow(c, c.in_[0][2], c.in_[0][0], c.in_[0][1], es3fShaderTextureFunctionTests.computeLodFromGrad2D(c));
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTextureCubeShadowGrad = function(c, p) {
        c.color[0] = es3fShaderTextureFunctionTests.textureCubeShadow(c, c.in_[0][3], c.in_[0][0], c.in_[0][1], c.in_[0][2], es3fShaderTextureFunctionTests.computeLodFromGradCube(c));
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DArrayShadowGrad = function(c, p) {
        c.color[0] = es3fShaderTextureFunctionTests.texture2DArrayShadow(c, c.in_[0][3], c.in_[0][0], c.in_[0][1], c.in_[0][2], es3fShaderTextureFunctionTests.computeLodFromGrad2DArray(c));
    };


    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DGradOffset = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DOffset(c, c.in_[0][0], c.in_[0][1], es3fShaderTextureFunctionTests.computeLodFromGrad2D(c), deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DArrayGradOffset = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DArrayOffset(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], es3fShaderTextureFunctionTests.computeLodFromGrad2DArray(c), deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture3DGradOffset = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3DOffset(c, c.in_[0][0], c.in_[0][1], c.in_[0][2], es3fShaderTextureFunctionTests.computeLodFromGrad3D(c), p.offset), p.scale), p.bias);
    };


    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DShadowGradOffset = function(c, p) {
        c.color[0] = es3fShaderTextureFunctionTests.texture2DShadowOffset(c, c.in_[0][2], c.in_[0][0], c.in_[0][1], es3fShaderTextureFunctionTests.computeLodFromGrad2D(c), deMath.swizzle(p.offset, [0,1]));
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DArrayShadowGradOffset = function(c, p) {
        c.color[0] = es3fShaderTextureFunctionTests.texture2DArrayShadowOffset(c, c.in_[0][3], c.in_[0][0], c.in_[0][1], c.in_[0][2], es3fShaderTextureFunctionTests.computeLodFromGrad2DArray(c), deMath.swizzle(p.offset, [0,1]));
    };


    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DShadowProjGrad = function(c, p) {
        c.color[0] = es3fShaderTextureFunctionTests.texture2DShadow(c, c.in_[0][2]/c.in_[0][3], c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], es3fShaderTextureFunctionTests.computeLodFromGrad2D(c));
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DShadowProjGradOffset = function(c, p) {
        c.color[0] = es3fShaderTextureFunctionTests.texture2DShadowOffset(c, c.in_[0][2]/c.in_[0][3], c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], es3fShaderTextureFunctionTests.computeLodFromGrad2D(c), deMath.swizzle(p.offset, [0,1]));
    };


    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DProjGrad3 = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2D(c, c.in_[0][0]/c.in_[0][2], c.in_[0][1]/c.in_[0][2], es3fShaderTextureFunctionTests.computeLodFromGrad2D(c)), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DProjGrad = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2D(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], es3fShaderTextureFunctionTests.computeLodFromGrad2D(c)), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture3DProjGrad = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3D(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], c.in_[0][2]/c.in_[0][3], es3fShaderTextureFunctionTests.computeLodFromGrad3D(c)), p.scale), p.bias);
    };


    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DProjGrad3Offset = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DOffset(c, c.in_[0][0]/c.in_[0][2], c.in_[0][1]/c.in_[0][2], es3fShaderTextureFunctionTests.computeLodFromGrad2D(c), deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture2DProjGradOffset = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture2DOffset(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], es3fShaderTextureFunctionTests.computeLodFromGrad2D(c), deMath.swizzle(p.offset, [0,1])), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexture3DProjGradOffset = function(c, p) {
        c.color = deMath.add(deMath.multiply(es3fShaderTextureFunctionTests.texture3DOffset(c, c.in_[0][0]/c.in_[0][3], c.in_[0][1]/c.in_[0][3], c.in_[0][2]/c.in_[0][3], es3fShaderTextureFunctionTests.computeLodFromGrad3D(c), p.offset), p.scale), p.bias);
    };

    // Texel fetch variants
    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexelFetch2D = function(c, p) {
        /** @type {number} */ var x    = Math.trunc(c.in_[0][0]) + p.offset[0];
        /** @type {number} */ var y    = Math.trunc(c.in_[0][1]) + p.offset[1];
        /** @type {number} */ var lod = Math.trunc(c.in_[1][0]);
        c.color = deMath.add(deMath.multiply(c.textures[0].tex2D.getLevel(lod).getPixel(x, y), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexelFetch2DArray = function(c, p) {
        /** @type {number} */ var x    = Math.trunc(c.in_[0][0]) + p.offset[0];
        /** @type {number} */ var y    = Math.trunc(c.in_[0][1]) + p.offset[1];
        /** @type {number} */ var l    = Math.trunc(c.in_[0][2]);
        /** @type {number} */ var lod = Math.trunc(c.in_[1][0]);
        c.color = deMath.add(deMath.multiply(c.textures[0].tex2DArray.getLevel(lod).getPixel(x, y, l), p.scale), p.bias);
    };

    /**
     * @param {glsShaderRenderCase.ShaderEvalContext} c
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} p
     */
    es3fShaderTextureFunctionTests.evalTexelFetch3D = function(c, p) {
        /** @type {number} */ var x    = Math.trunc(c.in_[0][0]) + p.offset[0];
        /** @type {number} */ var y    = Math.trunc(c.in_[0][1]) + p.offset[1];
        /** @type {number} */ var z    = Math.trunc(c.in_[0][2]) + p.offset[2];
        /** @type {number} */ var lod = Math.trunc(c.in_[1][0]);
        c.color = deMath.add(deMath.multiply(c.textures[0].tex3D.getLevel(lod).getPixel(x, y, z), p.scale), p.bias);
    };

    /**
     * @constructor
     * @extends {glsShaderRenderCase.ShaderEvaluator}
     * @param {es3fShaderTextureFunctionTests.TexEvalFunc} evalFunc
     * @param {es3fShaderTextureFunctionTests.TexLookupParams} lookupParams
     */
    es3fShaderTextureFunctionTests.TexLookupEvaluator = function(evalFunc, lookupParams) {
        /** @type {es3fShaderTextureFunctionTests.TexEvalFunc} */ this.m_evalFunc = evalFunc;
        /** @type {es3fShaderTextureFunctionTests.TexLookupParams} */ this.m_lookupParams = lookupParams;
    };

    es3fShaderTextureFunctionTests.TexLookupEvaluator.prototype = Object.create(glsShaderRenderCase.ShaderEvaluator.prototype);
    es3fShaderTextureFunctionTests.TexLookupEvaluator.prototype.constructor = es3fShaderTextureFunctionTests.TexLookupEvaluator;

    /**
     * @param  {glsShaderRenderCase.ShaderEvalContext} ctx
     */
    es3fShaderTextureFunctionTests.TexLookupEvaluator.prototype.evaluate = function(ctx) {
        this.m_evalFunc(ctx, this.m_lookupParams);
    };

    /**
     * @constructor
     * @extends {glsShaderRenderCase.ShaderRenderCase}
     * @param {string} name
     * @param {string} desc
     * @param {es3fShaderTextureFunctionTests.TextureLookupSpec} lookup
     * @param {es3fShaderTextureFunctionTests.TextureSpec} texture
     * @param {es3fShaderTextureFunctionTests.TexEvalFunc} evalFunc
     * @param {boolean} isVertexCase
     */
    es3fShaderTextureFunctionTests.ShaderTextureFunctionCase = function(name, desc, lookup, texture, evalFunc, isVertexCase) {
        glsShaderRenderCase.ShaderRenderCase.call(this, name, desc, isVertexCase);

        /** @type {es3fShaderTextureFunctionTests.TextureLookupSpec} */ this.m_lookupSpec = lookup;
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ this.m_textureSpec = texture;
        /** @type {es3fShaderTextureFunctionTests.TexLookupParams} */ this.m_lookupParams = new es3fShaderTextureFunctionTests.TexLookupParams();
        /** @type {es3fShaderTextureFunctionTests.TexLookupEvaluator} */ this.m_evaluator = new es3fShaderTextureFunctionTests.TexLookupEvaluator(evalFunc, this.m_lookupParams);

        /** @type {gluTexture.Texture2D} */ this.m_texture2D = null;
        /** @type {gluTexture.TextureCube} */ this.m_textureCube = null;
        /** @type {gluTexture.Texture2DArray} */ this.m_texture2DArray = null;
        /** @type {gluTexture.Texture3D} */ this.m_texture3D = null;
    };

    es3fShaderTextureFunctionTests.ShaderTextureFunctionCase.prototype = Object.create(glsShaderRenderCase.ShaderRenderCase.prototype);
    es3fShaderTextureFunctionTests.ShaderTextureFunctionCase.prototype.constructor = es3fShaderTextureFunctionTests.ShaderTextureFunctionCase;

    es3fShaderTextureFunctionTests.ShaderTextureFunctionCase.prototype.init = function() {

        // Base coord scale & bias
        /** @type {(Array<number>|number)} */ var s = deMath.subtract(this.m_lookupSpec.maxCoord, this.m_lookupSpec.minCoord);
        /** @type {(Array<number>|number)} */ var b = this.m_lookupSpec.minCoord;

        /** @type {Array<number>} */ var baseCoordTrans = [
            s[0], 0.0, 0.0, b[0],
            0.0, s[1], 0., b[1],
            s[2]/2.0, -s[2]/2.0, 0.0, s[2]/2.0 + b[2],
            -s[3]/2.0, s[3]/2.0, 0.0, s[3]/2.0 + b[3]
        ];
        this.m_userAttribTransforms.push(tcuMatrix.matrixFromArray(4, 4, baseCoordTrans));

        /** @type {boolean} */ var hasLodBias = es3fShaderTextureFunctionTests.functionHasLod(this.m_lookupSpec.func) || this.m_lookupSpec.useBias;
        /** @type {boolean} */ var isGrad = es3fShaderTextureFunctionTests.functionHasGrad(this.m_lookupSpec.func);
        assertMsgOptions(!isGrad || !hasLodBias, 'Assert Error. expected: isGrad || hasLodBias === false', false, true);

        if (hasLodBias) {
            s = this.m_lookupSpec.maxLodBias - this.m_lookupSpec.minLodBias;
            b = this.m_lookupSpec.minLodBias;
            /** @type {Array<number>} */ var lodCoordTrans = [
                s/2.0, s/2.0, 0.0, b,
                0.0, 0.0, 0.0, 0.0,
                0.0, 0.0, 0.0, 0.0,
                0.0, 0.0, 0.0, 0.0
            ];

            this.m_userAttribTransforms.push(tcuMatrix.matrixFromArray(4, 4, lodCoordTrans));
        }
        else if (isGrad) {
            /** @type {Array<number>} */ var sx = deMath.subtract(this.m_lookupSpec.maxDX, this.m_lookupSpec.minDX);
            /** @type {Array<number>} */ var sy = deMath.subtract(this.m_lookupSpec.maxDY, this.m_lookupSpec.minDY);
            /** @type {Array<number>} */ var gradDxTrans = [
                sx[0]/2.0, sx[0]/2.0, 0.0, this.m_lookupSpec.minDX[0],
                sx[1]/2.0, sx[1]/2.0, 0.0, this.m_lookupSpec.minDX[1],
                sx[2]/2.0, sx[2]/2.0, 0.0, this.m_lookupSpec.minDX[2],
                0.0, 0.0, 0.0, 0.0
            ];
            /** @type {Array<number>} */ var gradDyTrans = [
                -sy[0]/2.0, -sy[0]/2.0, 0.0, this.m_lookupSpec.maxDY[0],
                -sy[1]/2.0, -sy[1]/2.0, 0.0, this.m_lookupSpec.maxDY[1],
                -sy[2]/2.0, -sy[2]/2.0, 0.0, this.m_lookupSpec.maxDY[2],
                0.0, 0.0, 0.0, 0.0
             ];

            this.m_userAttribTransforms.push(tcuMatrix.matrixFromArray(4, 4, gradDxTrans));
            this.m_userAttribTransforms.push(tcuMatrix.matrixFromArray(4, 4, gradDyTrans));
        }

        this.initShaderSources();
        this.initTexture();

        this.postinit();

    };

    es3fShaderTextureFunctionTests.ShaderTextureFunctionCase.prototype.initTexture = function() {
        /** @type {Array<Array<number>>} */ var texCubeSwz = [
            [0, 0, 1, 1],
            [1, 1, 0, 0],
            [0, 1, 0, 1],
            [1, 0, 1, 0],
            [0, 1, 1, 0],
            [1, 0, 0, 1]
        ];

        assertMsgOptions(texCubeSwz.length === 6, 'Cube should have 6 faces.', false, true);

        /** @type {number} */ var levelStep;
        /** @type {Array<number>} */ var cScale;
        /** @type {Array<number>} */ var cBias;
        /** @type {number} */ var baseCellSize;

        /** @type {number} */ var fA;
        /** @type {number} */ var fB;
        /** @type {Array<number>} */ var colorA;
        /** @type {Array<number>} */ var colorB;

        /** @type {number} */ var dudx;
        /** @type {number} */ var dvdy;

        /** @type {tcuTexture.TextureFormat} */ var texFmt = gluTextureUtil.mapGLInternalFormat(this.m_textureSpec.format);
        /** @type {tcuTextureUtil.TextureFormatInfo} */ var fmtInfo = tcuTextureUtil.getTextureFormatInfo(texFmt);
        /** @type {Array<number>} */ var viewportSize = this.getViewportSize();
        /** @type {boolean} */ var isProj = es3fShaderTextureFunctionTests.functionHasProj(this.m_lookupSpec.func);
        /** @type {boolean} */ var isAutoLod = es3fShaderTextureFunctionTests.functionHasAutoLod(
            this.m_isVertexCase ? gluShaderProgram.shaderType.VERTEX : gluShaderProgram.shaderType.FRAGMENT,
            this.m_lookupSpec.func); // LOD can vary significantly
        /** @type {number} */ var proj = isProj ?
            1.0 / this.m_lookupSpec.minCoord[this.m_lookupSpec.func === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3 ? 2 : 3] :
            1.0;

        switch (this.m_textureSpec.type) {
            case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D:
                levelStep = isAutoLod ? 0.0 : 1.0 / Math.max(1, this.m_textureSpec.numLevels - 1);
                cScale = deMath.subtract(fmtInfo.valueMax, fmtInfo.valueMin);
                cBias = fmtInfo.valueMin;
                baseCellSize = Math.min(this.m_textureSpec.width / 4, this.m_textureSpec.height / 4);

                this.m_texture2D = gluTexture.texture2DFromInternalFormat(gl, this.m_textureSpec.format, this.m_textureSpec.width, this.m_textureSpec.height);
                for (var level = 0; level < this.m_textureSpec.numLevels; level++) {
                    fA = level * levelStep;
                    fB = 1.0 - fA;
                    colorA = deMath.add(cBias, deMath.multiply(cScale, [fA, fB, fA, fB]));
                    colorB = deMath.add(cBias, deMath.multiply(cScale, [fB, fA, fB, fA]));

                    this.m_texture2D.getRefTexture().allocLevel(level);
                    tcuTextureUtil.fillWithGrid(this.m_texture2D.getRefTexture().getLevel(level), Math.max(1, baseCellSize >> level), colorA, colorB);
                }
                this.m_texture2D.upload();

                // Compute LOD.
                dudx = (this.m_lookupSpec.maxCoord[0] - this.m_lookupSpec.minCoord[0]) * proj * this.m_textureSpec.width / viewportSize[0];
                dvdy = (this.m_lookupSpec.maxCoord[1] - this.m_lookupSpec.minCoord[1]) * proj * this.m_textureSpec.height / viewportSize[1];
                this.m_lookupParams.lod = es3fShaderTextureFunctionTests.computeLodFromDerivates(dudx, 0.0, 0.0, dvdy);

                // Append to texture list.
                this.m_textures.push(new glsShaderRenderCase.TextureBinding(this.m_texture2D, this.m_textureSpec.sampler));
                break;

            case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP:
                levelStep = isAutoLod ? 0.0 : 1.0 / Math.max(1, this.m_textureSpec.numLevels - 1);
                cScale = deMath.subtract(fmtInfo.valueMax, fmtInfo.valueMin);
                cBias = fmtInfo.valueMin;
                /** @type {Array<number>} */ var cCorner = deMath.add(cBias, deMath.scale(cScale, 0.5));
                baseCellSize = Math.min(this.m_textureSpec.width / 4, this.m_textureSpec.height / 4);

                assertMsgOptions(this.m_textureSpec.width === this.m_textureSpec.height, 'Expected width === height', false, true);
                this.m_textureCube = gluTexture.cubeFromInternalFormat(gl, this.m_textureSpec.format, this.m_textureSpec.width);
                for (var level = 0; level < this.m_textureSpec.numLevels; level++) {
                    fA = level * levelStep;
                    fB = 1.0 - fA;
                    /** @type {Array<number>} */ var f = [fA, fB];

                    for (var face = 0; face < 6; face++) {
                        /** @type {Array<number>} */ var swzA = texCubeSwz[face];
                        /** @type {Array<number>} */ var swzB = deMath.subtract([1, 1, 1, 1], swzA);
                        colorA = deMath.add(cBias, deMath.multiply(cScale, deMath.swizzle(f, [swzA[0], swzA[1], swzA[2], swzA[3]])));
                        colorB = deMath.add(cBias, deMath.multiply(cScale, deMath.swizzle(f, [swzB[0], swzB[1], swzB[2], swzB[3]])));

                        this.m_textureCube.getRefTexture().allocLevel(face, level);

                        /** @type {tcuTexture.PixelBufferAccess} */ var access = this.m_textureCube.getRefTexture().getLevelFace(level, face);
                        /** @type {number} */ var lastPix = access.getWidth() - 1;

                        tcuTextureUtil.fillWithGrid(access, Math.max(1, baseCellSize >> level), colorA, colorB);

                        // Ensure all corners have identical colors in order to avoid dealing with ambiguous corner texel filtering
                        access.setPixel(cCorner, 0, 0);
                        access.setPixel(cCorner, 0, lastPix);
                        access.setPixel(cCorner, lastPix, 0);
                        access.setPixel(cCorner, lastPix, lastPix);
                    }
                }
                this.m_textureCube.upload();

                // Compute LOD \note Assumes that only single side is accessed and R is constant major axis.
                assertMsgOptions(Math.abs(this.m_lookupSpec.minCoord[2] - this.m_lookupSpec.maxCoord[2]) < 0.005, 'Expected abs(minCoord-maxCoord) < 0.005', false, true);
                assertMsgOptions(Math.abs(this.m_lookupSpec.minCoord[0]) < Math.abs(this.m_lookupSpec.minCoord[2]) && Math.abs(this.m_lookupSpec.maxCoord[0]) < Math.abs(this.m_lookupSpec.minCoord[2]), 'Assert error: minCoord, maxCoord', false, true);
                assertMsgOptions(Math.abs(this.m_lookupSpec.minCoord[1]) < Math.abs(this.m_lookupSpec.minCoord[2]) && Math.abs(this.m_lookupSpec.maxCoord[1]) < Math.abs(this.m_lookupSpec.minCoord[2]), 'Assert error: minCoord, maxCoord', false, true);

                /** @type {tcuTexture.CubeFaceCoords} */ var c00 = tcuTexture.getCubeFaceCoords([this.m_lookupSpec.minCoord[0] * proj, this.m_lookupSpec.minCoord[1] * proj, this.m_lookupSpec.minCoord[2] * proj]);
                /** @type {tcuTexture.CubeFaceCoords} */ var c10 = tcuTexture.getCubeFaceCoords([this.m_lookupSpec.maxCoord[0] * proj, this.m_lookupSpec.minCoord[1] * proj, this.m_lookupSpec.minCoord[2] * proj]);
                /** @type {tcuTexture.CubeFaceCoords} */ var c01 = tcuTexture.getCubeFaceCoords([this.m_lookupSpec.minCoord[0] * proj, this.m_lookupSpec.maxCoord[1] * proj, this.m_lookupSpec.minCoord[2] * proj]);
                dudx = (c10.s - c00.s) * this.m_textureSpec.width / viewportSize[0];
                dvdy = (c01.t - c00.t) * this.m_textureSpec.height / viewportSize[1];

                this.m_lookupParams.lod = es3fShaderTextureFunctionTests.computeLodFromDerivates(dudx, 0.0, 0.0, dvdy);

                this.m_textures.push(new glsShaderRenderCase.TextureBinding(this.m_textureCube, this.m_textureSpec.sampler));
                break;

            case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY:
                /** @type {number} */ var layerStep = 1.0 / this.m_textureSpec.depth;
                levelStep = isAutoLod ? 0.0 : 1.0 / (Math.max(1, this.m_textureSpec.numLevels - 1) * this.m_textureSpec.depth);
                cScale = deMath.subtract(fmtInfo.valueMax, fmtInfo.valueMin);
                cBias = fmtInfo.valueMin;
                baseCellSize = Math.min(this.m_textureSpec.width / 4, this.m_textureSpec.height / 4);

                this.m_texture2DArray = gluTexture.texture2DArrayFromInternalFormat(gl,
                    this.m_textureSpec.format,
                    this.m_textureSpec.width,
                    this.m_textureSpec.height,
                    this.m_textureSpec.depth);

                for (var level = 0; level < this.m_textureSpec.numLevels; level++) {
                    this.m_texture2DArray.getRefTexture().allocLevel(level);
                    /** @type {tcuTexture.PixelBufferAccess} */ var levelAccess = this.m_texture2DArray.getRefTexture().getLevel(level);

                    for (var layer = 0; layer < levelAccess.getDepth(); layer++) {
                        fA = layer * layerStep + level * levelStep;
                        fB = 1.0 - fA;
                        colorA = deMath.add(cBias, deMath.multiply(cScale, [fA, fB, fA, fB]));
                        colorB = deMath.add(cBias, deMath.multiply(cScale, [fB, fA, fB, fA]));

                        tcuTextureUtil.fillWithGrid(tcuTextureUtil.getSubregion(levelAccess, 0, 0, layer, levelAccess.getWidth(), levelAccess.getHeight(), 1), Math.max(1, baseCellSize >> level), colorA, colorB);
                    }
                }
                this.m_texture2DArray.upload();

                // Compute LOD.
                dudx = (this.m_lookupSpec.maxCoord[0] - this.m_lookupSpec.minCoord[0]) * proj * this.m_textureSpec.width / viewportSize[0];
                dvdy = (this.m_lookupSpec.maxCoord[1] - this.m_lookupSpec.minCoord[1]) * proj * this.m_textureSpec.height / viewportSize[1];
                this.m_lookupParams.lod = es3fShaderTextureFunctionTests.computeLodFromDerivates(dudx, 0.0, 0.0, dvdy);

                // Append to texture list.
                this.m_textures.push(new glsShaderRenderCase.TextureBinding(this.m_texture2DArray, this.m_textureSpec.sampler));
                break;

            case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D:
                levelStep = isAutoLod ? 0.0 : 1.0 / Math.max(1, this.m_textureSpec.numLevels - 1);
                cScale = deMath.subtract(fmtInfo.valueMax, fmtInfo.valueMin);
                cBias = fmtInfo.valueMin;
                baseCellSize = Math.min(this.m_textureSpec.width / 2, this.m_textureSpec.height / 2, this.m_textureSpec.depth / 2);

                this.m_texture3D = gluTexture.texture3DFromInternalFormat(gl, this.m_textureSpec.format, this.m_textureSpec.width, this.m_textureSpec.height, this.m_textureSpec.depth);
                for (var level = 0; level < this.m_textureSpec.numLevels; level++) {
                    fA = level * levelStep;
                    fB = 1.0 - fA;
                    colorA = deMath.add(cBias, deMath.multiply(cScale, [fA, fB, fA, fB]));
                    colorB = deMath.add(cBias, deMath.multiply(cScale, [fB, fA, fB, fA]));

                    this.m_texture3D.getRefTexture().allocLevel(level);
                    tcuTextureUtil.fillWithGrid(this.m_texture3D.getRefTexture().getLevel(level), Math.max(1, baseCellSize >> level), colorA, colorB);
                }
                this.m_texture3D.upload();

                // Compute LOD.
                dudx = (this.m_lookupSpec.maxCoord[0] - this.m_lookupSpec.minCoord[0]) * proj * this.m_textureSpec.width / viewportSize[0];
                dvdy = (this.m_lookupSpec.maxCoord[1] - this.m_lookupSpec.minCoord[1]) * proj * this.m_textureSpec.height / viewportSize[1];
                /** @type {number} */ var dwdx = (this.m_lookupSpec.maxCoord[2] - this.m_lookupSpec.minCoord[2]) * 0.5 * proj * this.m_textureSpec.depth / viewportSize[0];
                /** @type {number} */ var dwdy = (this.m_lookupSpec.maxCoord[2] - this.m_lookupSpec.minCoord[2]) * 0.5 * proj * this.m_textureSpec.depth / viewportSize[1];
                this.m_lookupParams.lod = es3fShaderTextureFunctionTests.computeLodFromDerivates(dudx, 0.0, dwdx, 0.0, dvdy, dwdy);

                // Append to texture list.
                this.m_textures.push(new glsShaderRenderCase.TextureBinding(this.m_texture3D, this.m_textureSpec.sampler));
                break;

            default:
                throw new Error('Texture type not supported.');
        }

        // Set lookup scale & bias
        this.m_lookupParams.scale = fmtInfo.lookupScale;
        this.m_lookupParams.bias = fmtInfo.lookupBias;
        this.m_lookupParams.offset = this.m_lookupSpec.offset;
    };

    es3fShaderTextureFunctionTests.ShaderTextureFunctionCase.prototype.initShaderSources = function() {
        /** @type {es3fShaderTextureFunctionTests.TexFunction} */ var function_ = this.m_lookupSpec.func;
        /** @type {boolean} */ var isVtxCase = this.m_isVertexCase;
        /** @type {boolean} */ var isProj = es3fShaderTextureFunctionTests.functionHasProj(function_);
        /** @type {boolean} */ var isGrad = es3fShaderTextureFunctionTests.functionHasGrad(function_);
        /** @type {boolean} */ var isShadow = this.m_textureSpec.sampler.compare !== tcuTexture.CompareMode.COMPAREMODE_NONE;
        /** @type {boolean} */ var is2DProj4 = !isShadow && this.m_textureSpec.type === es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D && (function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ || function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD || function_ === es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD);
        /** @type {boolean} */ var isIntCoord = function_ === es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH;
        /** @type {boolean} */ var hasLodBias = es3fShaderTextureFunctionTests.functionHasLod(this.m_lookupSpec.func) || this.m_lookupSpec.useBias;
        /** @type {number} */ var texCoordComps = this.m_textureSpec.type === es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D ? 2 : 3;
        /** @type {number} */ var extraCoordComps = (isProj ? (is2DProj4 ? 2 : 1) : 0) + (isShadow ? 1 : 0);
        /** @type {gluShaderUtil.DataType} */ var coordType = gluShaderUtil.getDataTypeVector(gluShaderUtil.DataType.FLOAT, texCoordComps+extraCoordComps);
        /** @type {gluShaderUtil.precision} */ var coordPrec = gluShaderUtil.precision.PRECISION_HIGHP;
        /** @type {string} */ var coordTypeName = gluShaderUtil.getDataTypeName(coordType);
        /** @type {string} */ var coordPrecName = gluShaderUtil.getPrecisionName(coordPrec);
        /** @type {tcuTexture.TextureFormat} */ var texFmt = gluTextureUtil.mapGLInternalFormat(this.m_textureSpec.format);
        /** @type {?gluShaderUtil.DataType} */ var samplerType = null;
        /** @type {gluShaderUtil.DataType} */ var gradType = (this.m_textureSpec.type === es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP || this.m_textureSpec.type === es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D) ? gluShaderUtil.DataType.FLOAT_VEC3 : gluShaderUtil.DataType.FLOAT_VEC2;
        /** @type {string} */ var gradTypeName = gluShaderUtil.getDataTypeName(gradType);
        /** @type {string} */ var baseFuncName = '';

        assertMsgOptions(!isGrad || !hasLodBias, 'Expected !isGrad || !hasLodBias', false, true);

        switch (this.m_textureSpec.type) {
            case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D:
                samplerType = isShadow ? gluShaderUtil.DataType.SAMPLER_2D_SHADOW : gluTextureUtil.getSampler2DType(texFmt);
                break;
            case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP:
                samplerType = isShadow ? gluShaderUtil.DataType.SAMPLER_CUBE_SHADOW : gluTextureUtil.getSamplerCubeType(texFmt);
                break;
            case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY:
                samplerType = isShadow ? gluShaderUtil.DataType.SAMPLER_2D_ARRAY_SHADOW : gluTextureUtil.getSampler2DArrayType(texFmt);
                break;
            case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D:
                assertMsgOptions(!isShadow, 'Expected !isShadow', false, true);
                samplerType = gluTextureUtil.getSampler3DType(texFmt);
                break;
            default:
                throw new Error('Unexpected type.');
        }

        switch (this.m_lookupSpec.func) {
            case es3fShaderTextureFunctionTests.TexFunction.TEXTURE: baseFuncName = 'texture'; break;
            case es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ: baseFuncName = 'textureProj'; break;
            case es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3: baseFuncName = 'textureProj'; break;
            case es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD: baseFuncName = 'textureLod'; break;
            case es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD: baseFuncName = 'textureProjLod'; break;
            case es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD3: baseFuncName = 'textureProjLod'; break;
            case es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD: baseFuncName = 'textureGrad'; break;
            case es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD: baseFuncName = 'textureProjGrad'; break;
            case es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD3: baseFuncName = 'textureProjGrad'; break;
            case es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH: baseFuncName = 'texelFetch'; break;
            default:
                throw new Error('Unexpected function.');
        }

        /** @type {string} */ var vert = '';
        /** @type {string} */ var frag = '';
        /** @type {string} */ var op = '';

        vert += '#version 300 es\n' +
                'in highp vec4 a_position;\n' +
                'in ' + coordPrecName + ' ' + coordTypeName + ' a_in0;\n';

        if (isGrad) {
            vert += 'in ' + coordPrecName + ' ' + gradTypeName + ' a_in1;\n';
            vert += 'in ' + coordPrecName + ' ' + gradTypeName + ' a_in2;\n';
        }
        else if (hasLodBias)
            vert += 'in ' + coordPrecName + ' float a_in1;\n';

        frag += '#version 300 es\n' +
                'layout(location = 0) out mediump vec4 o_color;\n';

        if (isVtxCase) {
            vert += 'out mediump vec4 v_color;\n';
            frag += 'in mediump vec4 v_color;\n';
        }
        else
        {
            vert += 'out ' + coordPrecName + ' ' + coordTypeName + ' v_texCoord;\n';
            frag += 'in ' + coordPrecName + ' ' + coordTypeName + ' v_texCoord;\n';

            if (isGrad) {
                vert += 'out ' + coordPrecName + ' ' + gradTypeName + ' v_gradX;\n';
                vert += 'out ' + coordPrecName + ' ' + gradTypeName + ' v_gradY;\n';
                frag += 'in ' + coordPrecName + ' ' + gradTypeName + ' v_gradX;\n';
                frag += 'in ' + coordPrecName + ' ' + gradTypeName + ' v_gradY;\n';
            }

            if (hasLodBias) {
                vert += 'out ' + coordPrecName + ' float v_lodBias;\n';
                frag += 'in ' + coordPrecName + ' float v_lodBias;\n';
            }
        }

        // Uniforms
        op += 'uniform highp ' + gluShaderUtil.getDataTypeName(samplerType) + ' u_sampler;\n' +
              'uniform highp vec4 u_scale;\n' +
              'uniform highp vec4 u_bias;\n';

        vert += isVtxCase ? op : '';
        frag += isVtxCase ? '' : op;
        op = '';

        vert += '\nvoid main()\n{\n' +
                '\tgl_Position = a_position;\n';
        frag += '\nvoid main()\n{\n';

        if (isVtxCase)
            vert += '\tv_color = ';
        else
            frag += '\to_color = ';

        // Op.
        /** @type {string} */ var texCoord = isVtxCase ? 'a_in0' : 'v_texCoord';
        /** @type {string} */ var gradX = isVtxCase ? 'a_in1' : 'v_gradX';
        /** @type {string} */ var gradY = isVtxCase ? 'a_in2' : 'v_gradY';
        /** @type {string} */ var lodBias = isVtxCase ? 'a_in1' : 'v_lodBias';

        op += 'vec4(' + baseFuncName;
        if (this.m_lookupSpec.useOffset)
            op += 'Offset';
        op += '(u_sampler, ';

        if (isIntCoord)
            op += 'ivec' + (texCoordComps+extraCoordComps) + '(';

        op += texCoord;

        if (isIntCoord)
            op += ')';

        if (isGrad)
            op += ', ' + gradX + ', ' + gradY;

        if (es3fShaderTextureFunctionTests.functionHasLod(function_)) {
            if (isIntCoord)
                op += ', int(' + lodBias + ')';
            else
                op += ', ' + lodBias;
        }

        if (this.m_lookupSpec.useOffset) {
            /** @type {number} */ var offsetComps = this.m_textureSpec.type === es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D ? 3 : 2;

            op += ', ivec' + offsetComps + '(';
            for (var ndx = 0; ndx < offsetComps; ndx++) {
                if (ndx !== 0)
                    op += ', ';
                op += this.m_lookupSpec.offset[ndx];
            }
            op += ')';
        }

        if (this.m_lookupSpec.useBias)
            op += ', ' + lodBias;

        op += ')';

        if (isShadow)
            op += ', 0.0, 0.0, 1.0)';
        else
            op += ')*u_scale + u_bias';

        op += ';\n';

        vert += isVtxCase ? op : '';
        frag += isVtxCase ? '' : op;
        op = '';

        if (isVtxCase)
            frag += '\to_color = v_color;\n';
        else {
            vert += '\tv_texCoord = a_in0;\n';

            if (isGrad) {
                vert += '\tv_gradX = a_in1;\n';
                vert += '\tv_gradY = a_in2;\n';
            }
            else if (hasLodBias)
                vert += '\tv_lodBias = a_in1;\n';
        }

        vert += '}\n';
        frag += '}\n';

        this.m_vertShaderSource = vert;
        this.m_fragShaderSource = frag;
    };

    es3fShaderTextureFunctionTests.ShaderTextureFunctionCase.prototype.deinit = function() {
        this.m_program = null;
        this.m_texture2D = null;
        this.m_textureCube = null;
        this.m_texture2DArray = null;
        this.m_texture3D = null;
    };

    /**
     * @param  {WebGLProgram} programID
     * @param  {Array<number>} constCoords
     */
    es3fShaderTextureFunctionTests.ShaderTextureFunctionCase.prototype.setupUniforms = function(programID, constCoords) {
        gl.uniform1i(gl.getUniformLocation(programID, 'u_sampler'), 0);
        gl.uniform4fv(gl.getUniformLocation(programID, 'u_scale'), this.m_lookupParams.scale);
        gl.uniform4fv(gl.getUniformLocation(programID, 'u_bias'), this.m_lookupParams.bias);
    };


    /**
     * @struct
     * @constructor
     * @param {Array<number>} textureSize
     * @param {number} lod
     * @param {number} lodBase
     * @param {Array<number>} expectedSize
     */
    es3fShaderTextureFunctionTests.TestSize = function(textureSize, lod, lodBase, expectedSize) {
        /** @type {Array<number>} */ this.textureSize = textureSize;
        /** @type {number} */ this.lod = lod;
        /** @type {number} */ this.lodBase = lodBase;
        /** @type {Array<number>} */ this.expectedSize = expectedSize;
    };

    /**
     * @constructor
     * @extends {tcuTestCase.DeqpTest}
     * @param {string} name
     * @param {string} desc
     * @param {string} samplerType
     * @param {es3fShaderTextureFunctionTests.TextureSpec} texture
     * @param {boolean} isVertexCase
     */
    es3fShaderTextureFunctionTests.TextureSizeCase = function(name, desc, samplerType, texture, isVertexCase) {
        tcuTestCase.DeqpTest.call(this, name, desc);
        /** @type {string} */ this.m_samplerTypeStr = samplerType;
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ this.m_textureSpec = texture;
        /** @type {boolean} */ this.m_isVertexCase = isVertexCase;
        /** @type {boolean} */ this.m_has3DSize = texture.type === es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D || texture.type === es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY;
        /** @type {?gluShaderProgram.ShaderProgram} */ this.m_program = null;
        /** @type {number} */ this.m_iterationCounter = 0;
    };

    es3fShaderTextureFunctionTests.TextureSizeCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
    es3fShaderTextureFunctionTests.TextureSizeCase.prototype.constructor = es3fShaderTextureFunctionTests.TextureSizeCase;

    es3fShaderTextureFunctionTests.TextureSizeCase.prototype.deinit = function() {
        this.freeShader();
    };

    /**
     * @return {tcuTestCase.IterateResult}
     */
    es3fShaderTextureFunctionTests.TextureSizeCase.prototype.iterate = function() {
        /** @type {number} */ var currentIteration = this.m_iterationCounter++;
        /** @type {Array<es3fShaderTextureFunctionTests.TestSize>} */ var testSizes = [
            new es3fShaderTextureFunctionTests.TestSize([1, 2, 1], 1, 0, [1, 1, 1]),
            new es3fShaderTextureFunctionTests.TestSize([1, 2, 1], 0, 0, [1, 2, 1]),

            new es3fShaderTextureFunctionTests.TestSize([1, 3, 2], 0, 0, [1, 3, 2]),
            new es3fShaderTextureFunctionTests.TestSize([1, 3, 2], 1, 0, [1, 1, 1]),

            new es3fShaderTextureFunctionTests.TestSize([100, 31, 18], 0, 0, [100, 31, 18]),
            new es3fShaderTextureFunctionTests.TestSize([100, 31, 18], 1, 0, [50, 15, 9]),
            new es3fShaderTextureFunctionTests.TestSize([100, 31, 18], 2, 0, [25, 7, 4]),
            new es3fShaderTextureFunctionTests.TestSize([100, 31, 18], 3, 0, [12, 3, 2]),
            new es3fShaderTextureFunctionTests.TestSize([100, 31, 18], 4, 0, [6, 1, 1]),
            new es3fShaderTextureFunctionTests.TestSize([100, 31, 18], 5, 0, [3, 1, 1]),
            new es3fShaderTextureFunctionTests.TestSize([100, 31, 18], 6, 0, [1, 1, 1]),

            new es3fShaderTextureFunctionTests.TestSize([100, 128, 32], 0, 0, [100, 128, 32]),
            new es3fShaderTextureFunctionTests.TestSize([100, 128, 32], 1, 0, [50, 64, 16]),
            new es3fShaderTextureFunctionTests.TestSize([100, 128, 32], 2, 0, [25, 32, 8]),
            new es3fShaderTextureFunctionTests.TestSize([100, 128, 32], 3, 0, [12, 16, 4]),
            new es3fShaderTextureFunctionTests.TestSize([100, 128, 32], 4, 0, [6, 8, 2]),
            new es3fShaderTextureFunctionTests.TestSize([100, 128, 32], 5, 0, [3, 4, 1]),
            new es3fShaderTextureFunctionTests.TestSize([100, 128, 32], 6, 0, [1, 2, 1]),
            new es3fShaderTextureFunctionTests.TestSize([100, 128, 32], 7, 0, [1, 1, 1]),

            // pow 2
            new es3fShaderTextureFunctionTests.TestSize([128, 64, 32], 0, 0, [128, 64, 32]),
            new es3fShaderTextureFunctionTests.TestSize([128, 64, 32], 1, 0, [64, 32, 16]),
            new es3fShaderTextureFunctionTests.TestSize([128, 64, 32], 2, 0, [32, 16, 8]),
            new es3fShaderTextureFunctionTests.TestSize([128, 64, 32], 3, 0, [16, 8, 4]),
            new es3fShaderTextureFunctionTests.TestSize([128, 64, 32], 4, 0, [8, 4, 2]),
            new es3fShaderTextureFunctionTests.TestSize([128, 64, 32], 5, 0, [4, 2, 1]),
            new es3fShaderTextureFunctionTests.TestSize([128, 64, 32], 6, 0, [2, 1, 1]),
            new es3fShaderTextureFunctionTests.TestSize([128, 64, 32], 7, 0, [1, 1, 1]),

            // w === h
            new es3fShaderTextureFunctionTests.TestSize([1, 1, 1], 0, 0, [1, 1, 1]),
            new es3fShaderTextureFunctionTests.TestSize([64, 64, 64], 0, 0, [64, 64, 64]),
            new es3fShaderTextureFunctionTests.TestSize([64, 64, 64], 1, 0, [32, 32, 32]),
            new es3fShaderTextureFunctionTests.TestSize([64, 64, 64], 2, 0, [16, 16, 16]),
            new es3fShaderTextureFunctionTests.TestSize([64, 64, 64], 3, 0, [8, 8, 8]),
            new es3fShaderTextureFunctionTests.TestSize([64, 64, 64], 4, 0, [4, 4, 4]),

            // with lod base
            new es3fShaderTextureFunctionTests.TestSize([100, 31, 18], 3, 1, [6, 1, 1]),
            new es3fShaderTextureFunctionTests.TestSize([128, 64, 32], 3, 1, [8, 4, 2]),
            new es3fShaderTextureFunctionTests.TestSize([64, 64, 64], 1, 1, [16, 16, 16])

        ];
        /** @type {number} */ var lastIterationIndex = testSizes.length + 1;

        if (currentIteration === 0) {
            return this.initShader() ? tcuTestCase.IterateResult.CONTINUE : tcuTestCase.IterateResult.STOP;
        }
        else if (currentIteration === lastIterationIndex) {
            this.freeShader();
            return tcuTestCase.IterateResult.STOP;
        }
        else {
            if (!this.testTextureSize(testSizes[currentIteration - 1]))
                testFailedOptions('Fail: Case ' + (currentIteration - 1) + ' Got unexpected texture size', false);
            else
                testPassedOptions('Pass', true);

            return tcuTestCase.IterateResult.CONTINUE;
        }
    };

    /**
     * @return {boolean}
     */
    es3fShaderTextureFunctionTests.TextureSizeCase.prototype.initShader = function() {
        /** @type {string} */ var vertSrc = this.genVertexShader();
        /** @type {string} */ var fragSrc = this.genFragmentShader();

        assertMsgOptions(this.m_program === null, 'Program should be null', false, true);
        this.m_program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertSrc, fragSrc));

        if (!this.m_program.isOk()) {
            testFailedOptions('Fail: Shader failed', false);
            return false;
        }

        return true;
    };

    es3fShaderTextureFunctionTests.TextureSizeCase.prototype.freeShader = function() {
        this.m_program = null;
    };

    /**
     * @param {es3fShaderTextureFunctionTests.TestSize} testSize
     * @return {boolean}
     */
    es3fShaderTextureFunctionTests.TextureSizeCase.prototype.testTextureSize = function(testSize) {
        /** @type {Array<number>} */ var triangle = [ // covers entire viewport
            -1, -1, 0, 1, // was a 3x4 matrix
            4, -1, 0, 1,
            -1, 4, 0, 1
        ];

        /** @type {number} */ var positionLoc = gl.getAttribLocation(this.m_program.getProgram(), 'a_position');
        /** @type {WebGLUniformLocation} */ var samplerLoc = gl.getUniformLocation(this.m_program.getProgram(), 'u_sampler');
        /** @type {WebGLUniformLocation} */ var sizeLoc = gl.getUniformLocation(this.m_program.getProgram(), 'u_texSize');
        /** @type {WebGLUniformLocation} */ var lodLoc = gl.getUniformLocation(this.m_program.getProgram(), 'u_lod');
        /** @type {number} */ var textureTarget = this.getGLTextureTarget();
        /** @type {boolean} */ var isSquare = testSize.textureSize[0] === testSize.textureSize[1];
        /** @type {boolean} */ var is2DLodValid = (testSize.textureSize[0] >> (testSize.lod + testSize.lodBase)) !== 0 || (testSize.textureSize[1] >> (testSize.lod + testSize.lodBase)) !== 0;
        /** @type {boolean} */ var success = true;
        /** @type {number} */ var errorValue;

        // Skip incompatible cases
        if (this.m_textureSpec.type === es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP && !isSquare)
            return true;
        if (this.m_textureSpec.type === es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D && !is2DLodValid)
            return true;
        if (this.m_textureSpec.type === es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY && !is2DLodValid)
            return true;

        // setup rendering
        gl.useProgram(this.m_program.getProgram());
        gl.uniform1i(samplerLoc, 0);
        gl.clearColor(0.5, 0.5, 0.5, 1.0);
        gl.viewport(0, 0, 1, 1);

        /** @type {WebGLBuffer} */ var triangleGlBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, triangleGlBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangle), gl.STATIC_DRAW);

        gl.vertexAttribPointer(positionLoc, 4, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(positionLoc);

        // setup texture
        /** @type {number} */ var maxLevel = testSize.lod + testSize.lodBase;
        /** @type {number} */ var levels = maxLevel + 1;
        /** @type {?WebGLTexture} */ var texId = null;

        // gen texture
        texId = gl.createTexture();
        gl.bindTexture(textureTarget, texId);
        gl.texParameteri(textureTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
        gl.texParameteri(textureTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
        gl.texParameteri(textureTarget, gl.TEXTURE_BASE_LEVEL, testSize.lodBase);
        gl.texParameteri(textureTarget, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);

        // set up texture

        switch (this.m_textureSpec.type) {
            case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D:
                // bufferedLogToConsole('Testing image size ' + testSize.textureSize[0] + 'x' + testSize.textureSize[1] + 'x' + testSize.textureSize[2]);
                // bufferedLogToConsole('Lod: ' + testSize.lod + ', base level: ' + testSize.lodBase);
                // bufferedLogToConsole('Expecting: ' + testSize.expectedSize[0] + 'x' + testSize.expectedSize[1] + 'x' + testSize.expectedSize[2]);

                gl.uniform3iv(sizeLoc, testSize.expectedSize);
                gl.uniform1iv(lodLoc, [testSize.lod]);

                gl.texStorage3D(textureTarget, levels, this.m_textureSpec.format, testSize.textureSize[0], testSize.textureSize[1], testSize.textureSize[2]);
                break;

            case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D:
            case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP:
                // bufferedLogToConsole('Testing image size ' + testSize.textureSize[0] + 'x' + testSize.textureSize[1]);
                // bufferedLogToConsole('Lod: ' + testSize.lod + ', base level: ' + testSize.lodBase);
                // bufferedLogToConsole('Expecting: ' + testSize.expectedSize[0] + 'x' + testSize.expectedSize[1]);

                gl.uniform2iv(sizeLoc, testSize.expectedSize.slice(0,2));
                gl.uniform1iv(lodLoc, [testSize.lod]);

                gl.texStorage2D(textureTarget, levels, this.m_textureSpec.format, testSize.textureSize[0], testSize.textureSize[1]);
                break;

            case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY:
                /** @type {Array<number>} */ var expectedSize = [testSize.expectedSize[0], testSize.expectedSize[1], testSize.textureSize[2]];

                // bufferedLogToConsole('Testing image size ' + testSize.textureSize[0] + 'x' + testSize.textureSize[1] + ' with ' + testSize.textureSize[2] + ' layer(s)');
                // bufferedLogToConsole('Lod: ' + testSize.lod + ', base level: ' + testSize.lodBase);
                // bufferedLogToConsole('Expecting: ' + testSize.expectedSize[0] + 'x' + testSize.expectedSize[1] + ' and ' + testSize.textureSize[2] + ' layer(s)');

                gl.uniform3iv(sizeLoc, expectedSize);
                gl.uniform1iv(lodLoc, [testSize.lod]);

                gl.texStorage3D(textureTarget, levels, this.m_textureSpec.format, testSize.textureSize[0], testSize.textureSize[1], testSize.textureSize[2]);
                break;

            default:
                throw new Error('Type not supported');
        }

        // test
        /** @type {number} */ var colorTolerance = 0.1;
        /** @type {tcuSurface.Surface} */ var sample = new tcuSurface.Surface(1, 1);
        /** @type {Array<number>} */ var outputColor;

        gl.clear(gl.COLOR_BUFFER_BIT);
        gl.drawArrays(gl.TRIANGLES, 0, 3);
        gl.finish();

        sample.readViewport(gl, [0, 0, 1, 1]);

        outputColor = sample.getAccess().getPixel(0, 0);

        if (outputColor[0] >= 1.0 - colorTolerance &&
            outputColor[1] >= 1.0 - colorTolerance &&
            outputColor[2] >= 1.0 - colorTolerance)
            bufferedLogToConsole('Passed');
        else {
            // failure
            bufferedLogToConsole('Failed');
            success = false;
        }

        // free
        gl.bindTexture(textureTarget, null);
        gl.deleteTexture(texId);

        gl.useProgram(null);

        return success;
    };

    /**
     * @return {string}
     */
    es3fShaderTextureFunctionTests.TextureSizeCase.prototype.genVertexShader = function()  {
        /** @type {string} */ var vert = '';
        vert += '#version 300 es\n' +
                'in highp vec4 a_position;\n';

        if (this.m_isVertexCase) {
            vert += 'out mediump vec4 v_color;\n' +
                    'uniform highp ' + this.m_samplerTypeStr + ' u_sampler;\n' +
                    'uniform highp ivec' + (this.m_has3DSize ? 3 : 2) + ' u_texSize;\n' +
                    'uniform highp int u_lod;\n';
        }

        vert += 'void main()\n{\n';

        if (this.m_isVertexCase)
            vert += '    v_color = (textureSize(u_sampler, u_lod) == u_texSize ? vec4(1.0, 1.0, 1.0, 1.0) : vec4(0.0, 0.0, 0.0, 1.0));\n';

        vert += '    gl_Position = a_position;\n' +
                '}\n';

        return vert;
    };

    /**
     * @return {string}
     */
    es3fShaderTextureFunctionTests.TextureSizeCase.prototype.genFragmentShader = function()  {
        /** @type {string} */ var frag = '';

        frag += '#version 300 es\n' +
                'layout(location = 0) out mediump vec4 o_color;\n';

        if (this.m_isVertexCase)
                frag += 'in mediump vec4 v_color;\n';

        if (!this.m_isVertexCase) {
            frag += 'uniform highp ' + this.m_samplerTypeStr + ' u_sampler;\n' +
                    'uniform highp ivec' + (this.m_has3DSize ? 3 : 2) + ' u_texSize;\n' +
                    'uniform highp int u_lod;\n';
        }

        frag += 'void main()\n{\n';

        if (!this.m_isVertexCase)
            frag += '    o_color = (textureSize(u_sampler, u_lod) == u_texSize ? vec4(1.0, 1.0, 1.0, 1.0) : vec4(0.0, 0.0, 0.0, 1.0));\n';
        else
            frag += '    o_color = v_color;\n';

        frag += '}\n';

        return frag;
    };

    /**
     * @return {number}
     */
    es3fShaderTextureFunctionTests.TextureSizeCase.prototype.getGLTextureTarget = function()  {
        switch (this.m_textureSpec.type) {
            case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D:
                return gl.TEXTURE_2D;
            case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP:
                return gl.TEXTURE_CUBE_MAP;
            case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY:
                return gl.TEXTURE_2D_ARRAY;
            case es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D:
                return gl.TEXTURE_3D;
            default:
                throw new Error('Texture Type not supported.');
        }
    };

    /** @typedef {Array<string, es3fShaderTextureFunctionTests.TextureLookupSpec, es3fShaderTextureFunctionTests.TextureSpec, es3fShaderTextureFunctionTests.EvalFunc, es3fShaderTextureFunctionTests.CaseFlags>} */ es3fShaderTextureFunctionTests.TestSpec;

    /**
     * @param {string} name
     * @param {es3fShaderTextureFunctionTests.TexFunction} func
     * @param {Array<number>} minCoord
     * @param {Array<number>} maxCoord
     * @param {boolean} useBias
     * @param {number} minLodBias
     * @param {number} maxLodBias
     * @param {boolean} useOffset
     * @param {Array<number>} offset
     * @param {es3fShaderTextureFunctionTests.TextureSpec} texSpec
     * @param {es3fShaderTextureFunctionTests.TexEvalFunc} evalFunc
     * @param {es3fShaderTextureFunctionTests.CaseFlags} flags
     * @return {es3fShaderTextureFunctionTests.TexFuncCaseSpec}
     */
    es3fShaderTextureFunctionTests.getCaseSpec = function(name, func, minCoord, maxCoord, useBias, minLodBias, maxLodBias, useOffset, offset, texSpec, evalFunc, flags) {
        return new es3fShaderTextureFunctionTests.TexFuncCaseSpec(name,
            new es3fShaderTextureFunctionTests.TextureLookupSpec(func, minCoord, maxCoord, useBias, minLodBias, maxLodBias, [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], useOffset, offset),
            texSpec,
            evalFunc,
            flags);
    };

    /**
     * @param {string} name
     * @param {es3fShaderTextureFunctionTests.TexFunction} func
     * @param {Array<number>} minCoord
     * @param {Array<number>} maxCoord
     * @param {Array<number>} mindx
     * @param {Array<number>} maxdx
     * @param {Array<number>} mindy
     * @param {Array<number>} maxdy
     * @param {boolean} useOffset
     * @param {Array<number>} offset
     * @param {es3fShaderTextureFunctionTests.TextureSpec} texSpec
     * @param {es3fShaderTextureFunctionTests.TexEvalFunc} evalFunc
     * @param {es3fShaderTextureFunctionTests.CaseFlags} flags
     * @return {es3fShaderTextureFunctionTests.TexFuncCaseSpec}
     */
    es3fShaderTextureFunctionTests.getGradCaseSpec = function(name, func, minCoord, maxCoord, mindx, maxdx, mindy, maxdy, useOffset, offset, texSpec, evalFunc, flags) {
        return new es3fShaderTextureFunctionTests.TexFuncCaseSpec(name,
            new es3fShaderTextureFunctionTests.TextureLookupSpec(func, minCoord, maxCoord, false, 0.0, 0.0, mindx, maxdx, mindy, maxdy, useOffset, offset),
            texSpec,
            evalFunc,
            flags);
    };

    /**
     * @enum {number}
     */
    es3fShaderTextureFunctionTests.CaseFlags = {
        VERTEX: 1,
        FRAGMENT: 2,
        BOTH: 3
    };

    /**
     * @struct
     * @constructor
     * @param {string} name
     * @param {es3fShaderTextureFunctionTests.TextureLookupSpec} lookupSpec
     * @param {es3fShaderTextureFunctionTests.TextureSpec} texSpec
     * @param {es3fShaderTextureFunctionTests.TexEvalFunc} evalFunc
     * @param {number} flags
     */
    es3fShaderTextureFunctionTests.TexFuncCaseSpec = function(name, lookupSpec, texSpec, evalFunc, flags) {
        /** @type {string} */ this.name = name;
        /** @type {es3fShaderTextureFunctionTests.TextureLookupSpec} */ this.lookupSpec = lookupSpec;
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ this.texSpec = texSpec;
        /** @type {es3fShaderTextureFunctionTests.TexEvalFunc} */ this.evalFunc = evalFunc;
        /** @type {number} */ this.flags = flags;
    };

    /**
     * @param  {tcuTestCase.DeqpTest} parent
     * @param  {string} groupName
     * @param  {string} groupDesc
     * @param  {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} cases
     */
    es3fShaderTextureFunctionTests.createCaseGroup = function(parent, groupName, groupDesc, cases) {
        /** @type {tcuTestCase.DeqpTest} */ var group = tcuTestCase.newTest(groupName, groupDesc);
        parent.addChild(group);

        for (var ndx = 0; ndx < cases.length; ndx++) {
            /** @type {string} */ var name = cases[ndx].name;
            if (cases[ndx].flags & es3fShaderTextureFunctionTests.CaseFlags.VERTEX)
                group.addChild(new es3fShaderTextureFunctionTests.ShaderTextureFunctionCase(name + '_vertex', '', cases[ndx].lookupSpec, cases[ndx].texSpec, cases[ndx].evalFunc, true));
            if (cases[ndx].flags & es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT)
                group.addChild(new es3fShaderTextureFunctionTests.ShaderTextureFunctionCase(name + '_fragment', '', cases[ndx].lookupSpec, cases[ndx].texSpec, cases[ndx].evalFunc, false));
        }
    };

    /**
    * @constructor
    * @extends {tcuTestCase.DeqpTest}
    */
    es3fShaderTextureFunctionTests.ShaderTextureFunctionTests = function() {
        tcuTestCase.DeqpTest.call(this, 'texture_functions', 'Texture Access Function Tests');
    };

    es3fShaderTextureFunctionTests.ShaderTextureFunctionTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
    es3fShaderTextureFunctionTests.ShaderTextureFunctionTests.prototype.constructor = es3fShaderTextureFunctionTests.ShaderTextureFunctionTests;

    es3fShaderTextureFunctionTests.ShaderTextureFunctionTests.prototype.init = function() {
        // Samplers
        /** @type {tcuTexture.Sampler} */ var samplerNearestNoMipmap = new tcuTexture.Sampler(tcuTexture.WrapMode.REPEAT_GL, tcuTexture.WrapMode.REPEAT_GL, tcuTexture.WrapMode.REPEAT_GL,
                                                             tcuTexture.FilterMode.NEAREST, tcuTexture.FilterMode.NEAREST,
                                                             0.0 /* LOD threshold */, true /* normalized coords */, tcuTexture.CompareMode.COMPAREMODE_NONE,
                                                             0 /* cmp channel */, [0.0, 0.0, 0.0, 0.0] /* border color */, true /* seamless cube map */);
        /** @type {tcuTexture.Sampler} */ var samplerLinearNoMipmap = new tcuTexture.Sampler(tcuTexture.WrapMode.REPEAT_GL, tcuTexture.WrapMode.REPEAT_GL, tcuTexture.WrapMode.REPEAT_GL,
                                                             tcuTexture.FilterMode.LINEAR, tcuTexture.FilterMode.LINEAR,
                                                             0.0 /* LOD threshold */, true /* normalized coords */, tcuTexture.CompareMode.COMPAREMODE_NONE,
                                                             0 /* cmp channel */, [0.0, 0.0, 0.0, 0.0] /* border color */, true /* seamless cube map */);
        /** @type {tcuTexture.Sampler} */ var samplerNearestMipmap = new tcuTexture.Sampler(tcuTexture.WrapMode.REPEAT_GL, tcuTexture.WrapMode.REPEAT_GL, tcuTexture.WrapMode.REPEAT_GL,
                                                             tcuTexture.FilterMode.NEAREST_MIPMAP_NEAREST, tcuTexture.FilterMode.NEAREST,
                                                             0.0 /* LOD threshold */, true /* normalized coords */, tcuTexture.CompareMode.COMPAREMODE_NONE,
                                                             0 /* cmp channel */, [0.0, 0.0, 0.0, 0.0] /* border color */, true /* seamless cube map */);
        /** @type {tcuTexture.Sampler} */ var samplerLinearMipmap = new tcuTexture.Sampler(tcuTexture.WrapMode.REPEAT_GL, tcuTexture.WrapMode.REPEAT_GL, tcuTexture.WrapMode.REPEAT_GL,
                                                             tcuTexture.FilterMode.LINEAR_MIPMAP_NEAREST, tcuTexture.FilterMode.LINEAR,
                                                             0.0 /* LOD threshold */, true /* normalized coords */, tcuTexture.CompareMode.COMPAREMODE_NONE,
                                                             0 /* cmp channel */, [0.0, 0.0, 0.0, 0.0] /* border color */, true /* seamless cube map */);

        /** @type {tcuTexture.Sampler} */ var samplerShadowNoMipmap = new tcuTexture.Sampler(tcuTexture.WrapMode.REPEAT_GL, tcuTexture.WrapMode.REPEAT_GL, tcuTexture.WrapMode.REPEAT_GL,
                                                             tcuTexture.FilterMode.NEAREST, tcuTexture.FilterMode.NEAREST,
                                                             0.0 /* LOD threshold */, true /* normalized coords */, tcuTexture.CompareMode.COMPAREMODE_LESS,
                                                             0 /* cmp channel */, [0.0, 0.0, 0.0, 0.0] /* border color */, true /* seamless cube map */);
        /** @type {tcuTexture.Sampler} */ var samplerShadowMipmap = new tcuTexture.Sampler(tcuTexture.WrapMode.REPEAT_GL, tcuTexture.WrapMode.REPEAT_GL, tcuTexture.WrapMode.REPEAT_GL,
                                                             tcuTexture.FilterMode.NEAREST_MIPMAP_NEAREST, tcuTexture.FilterMode.NEAREST,
                                                             0.0 /* LOD threshold */, true /* normalized coords */, tcuTexture.CompareMode.COMPAREMODE_LESS,
                                                             0 /* cmp channel */, [0.0, 0.0, 0.0, 0.0] /* border color */, true /* seamless cube map */);

        /** @type {tcuTexture.Sampler} */ var samplerTexelFetch = new tcuTexture.Sampler(tcuTexture.WrapMode.REPEAT_GL, tcuTexture.WrapMode.REPEAT_GL, tcuTexture.WrapMode.REPEAT_GL,
                                                             tcuTexture.FilterMode.NEAREST_MIPMAP_NEAREST, tcuTexture.FilterMode.NEAREST,
                                                             0.0 /* LOD threshold */, false /* non-normalized coords */, tcuTexture.CompareMode.COMPAREMODE_NONE,
                                                             0 /* cmp channel */, [0.0, 0.0, 0.0, 0.0] /* border color */, true /* seamless cube map */);

        // Default textures.
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DFixed = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D, gl.RGBA8, 256, 256, 1, 1, samplerLinearNoMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DFloat = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D, gl.RGBA16F, 256, 256, 1, 1, samplerLinearNoMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DInt = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D, gl.RGBA8I, 256, 256, 1, 1, samplerNearestNoMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DUint = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D, gl.RGBA8UI, 256, 256, 1, 1, samplerNearestNoMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DMipmapFixed = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D, gl.RGBA8, 256, 256, 1, 9, samplerLinearMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DMipmapFloat = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D, gl.RGBA16F, 256, 256, 1, 9, samplerLinearMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DMipmapInt = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D, gl.RGBA8I, 256, 256, 1, 9, samplerNearestMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DMipmapUint = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D, gl.RGBA8UI, 256, 256, 1, 9, samplerNearestMipmap);

        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DShadow = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D, gl.DEPTH_COMPONENT16, 256, 256, 1, 9, samplerShadowNoMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DMipmapShadow = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D, gl.DEPTH_COMPONENT16, 256, 256, 1, 9, samplerShadowMipmap);

        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DTexelFetchFixed = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D, gl.RGBA8, 256, 256, 1, 9, samplerTexelFetch);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DTexelFetchFloat = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D, gl.RGBA16F, 256, 256, 1, 9, samplerTexelFetch);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DTexelFetchInt = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D, gl.RGBA8I, 256, 256, 1, 9, samplerTexelFetch);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DTexelFetchUint = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D, gl.RGBA8UI, 256, 256, 1, 9, samplerTexelFetch);

        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var texCubeFixed = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP, gl.RGBA8, 256, 256, 1, 1, samplerLinearNoMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var texCubeFloat = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP, gl.RGBA16F, 256, 256, 1, 1, samplerLinearNoMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var texCubeInt = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP, gl.RGBA8I, 256, 256, 1, 1, samplerNearestNoMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var texCubeUint = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP, gl.RGBA8UI, 256, 256, 1, 1, samplerNearestNoMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var texCubeMipmapFixed = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP, gl.RGBA8, 256, 256, 1, 9, samplerLinearMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var texCubeMipmapFloat = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP, gl.RGBA16F, 128, 128, 1, 8, samplerLinearMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var texCubeMipmapInt = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP, gl.RGBA8I, 256, 256, 1, 9, samplerNearestMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var texCubeMipmapUint = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP, gl.RGBA8UI, 256, 256, 1, 9, samplerNearestMipmap);

        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var texCubeShadow = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP, gl.DEPTH_COMPONENT16, 256, 256, 1, 1, samplerShadowNoMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var texCubeMipmapShadow = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_CUBE_MAP, gl.DEPTH_COMPONENT16, 256, 256, 1, 9, samplerShadowMipmap);

        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DArrayFixed = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY, gl.RGBA8, 128, 128, 4, 1, samplerLinearNoMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DArrayFloat = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY, gl.RGBA16F, 128, 128, 4, 1, samplerLinearNoMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DArrayInt = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY, gl.RGBA8I, 128, 128, 4, 1, samplerNearestNoMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DArrayUint = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY, gl.RGBA8UI, 128, 128, 4, 1, samplerNearestNoMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DArrayMipmapFixed = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY, gl.RGBA8, 128, 128, 4, 8, samplerLinearMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DArrayMipmapFloat = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY, gl.RGBA16F, 128, 128, 4, 8, samplerLinearMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DArrayMipmapInt = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY, gl.RGBA8I, 128, 128, 4, 8, samplerNearestMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DArrayMipmapUint = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY, gl.RGBA8UI, 128, 128, 4, 8, samplerNearestMipmap);

        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DArrayShadow = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY, gl.DEPTH_COMPONENT16, 128, 128, 4, 1, samplerShadowNoMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DArrayMipmapShadow = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY, gl.DEPTH_COMPONENT16, 128, 128, 4, 8, samplerShadowMipmap);

        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DArrayTexelFetchFixed = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY, gl.RGBA8, 128, 128, 4, 8, samplerTexelFetch);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DArrayTexelFetchFloat = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY, gl.RGBA16F, 128, 128, 4, 8, samplerTexelFetch);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DArrayTexelFetchInt = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY, gl.RGBA8I, 128, 128, 4, 8, samplerTexelFetch);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex2DArrayTexelFetchUint = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_2D_ARRAY, gl.RGBA8UI, 128, 128, 4, 8, samplerTexelFetch);

        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex3DFixed = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D, gl.RGBA8, 64, 32, 32, 1, samplerLinearNoMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex3DFloat = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D, gl.RGBA16F, 64, 32, 32, 1, samplerLinearNoMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex3DInt = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D, gl.RGBA8I, 64, 32, 32, 1, samplerNearestNoMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex3DUint = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D, gl.RGBA8UI, 64, 32, 32, 1, samplerNearestNoMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex3DMipmapFixed = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D, gl.RGBA8, 64, 32, 32, 7, samplerLinearMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex3DMipmapFloat = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D, gl.RGBA16F, 64, 32, 32, 7, samplerLinearMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex3DMipmapInt = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D, gl.RGBA8I, 64, 32, 32, 7, samplerNearestMipmap);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex3DMipmapUint = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D, gl.RGBA8UI, 64, 32, 32, 7, samplerNearestMipmap);

        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex3DTexelFetchFixed = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D, gl.RGBA8, 64, 32, 32, 7, samplerTexelFetch);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex3DTexelFetchFloat = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D, gl.RGBA16F, 64, 32, 32, 7, samplerTexelFetch);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex3DTexelFetchInt = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D, gl.RGBA8I, 64, 32, 32, 7, samplerTexelFetch);
        /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ var tex3DTexelFetchUint = new es3fShaderTextureFunctionTests.TextureSpec(es3fShaderTextureFunctionTests.TextureType.TEXTURETYPE_3D, gl.RGBA8UI, 64, 32, 32, 7, samplerTexelFetch);

        var testGroup = tcuTestCase.runner.testCases;
        // texture() cases
            /** @type {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} */ var textureCases = [
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DFixed, es3fShaderTextureFunctionTests.evalTexture2D, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2D, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DFloat, es3fShaderTextureFunctionTests.evalTexture2D, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2D, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DInt, es3fShaderTextureFunctionTests.evalTexture2D, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2D, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DUint, es3fShaderTextureFunctionTests.evalTexture2D, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2D, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_bias_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    true,    -2.0,    2.0,    false, [0, 0, 0],    tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_bias_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    true,    -2.0,    2.0,    false, [0, 0, 0],    tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    true,    -2.0,    2.0,    false, [0, 0, 0],    tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    true,    -2.0,    2.0,    false, [0, 0, 0],    tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getCaseSpec('samplercube_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, 1.01, 0.0], [1.0, 1.0, 1.01, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    texCubeFixed, es3fShaderTextureFunctionTests.evalTextureCube, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('samplercube_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, 1.01, 0.0], [1.0, 1.0, 1.01, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    texCubeMipmapFixed, es3fShaderTextureFunctionTests.evalTextureCube, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('samplercube_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, -1.01, 0.0], [1.0, 1.0, -1.01, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    texCubeFloat, es3fShaderTextureFunctionTests.evalTextureCube, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('samplercube_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, -1.01, 0.0], [1.0, 1.0, -1.01, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    texCubeMipmapFloat, es3fShaderTextureFunctionTests.evalTextureCube, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('isamplercube', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, 1.01, 0.0], [1.0, 1.0, 1.01, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    texCubeInt, es3fShaderTextureFunctionTests.evalTextureCube, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('isamplercube', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, 1.01, 0.0], [1.0, 1.0, 1.01, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    texCubeMipmapInt, es3fShaderTextureFunctionTests.evalTextureCube, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('usamplercube', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, -1.01, 0.0], [1.0, 1.0, -1.01, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    texCubeUint, es3fShaderTextureFunctionTests.evalTextureCube, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('usamplercube', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, -1.01, 0.0], [1.0, 1.0, -1.01, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    texCubeMipmapUint, es3fShaderTextureFunctionTests.evalTextureCube, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getCaseSpec('samplercube_bias_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, 1.01, 0.0], [1.0, 1.0, 1.01, 0.0],    true,    -2.0,    2.0,    false, [0, 0, 0],    texCubeMipmapFixed, es3fShaderTextureFunctionTests.evalTextureCubeBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('samplercube_bias_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, -1.01, 0.0], [1.0, 1.0, -1.01, 0.0],    true,    -2.0,    2.0,    false, [0, 0, 0],    texCubeMipmapFloat, es3fShaderTextureFunctionTests.evalTextureCubeBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('isamplercube_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, 1.01, 0.0], [1.0, 1.0, 1.01, 0.0],    true,    -2.0,    2.0,    false, [0, 0, 0],    texCubeMipmapInt, es3fShaderTextureFunctionTests.evalTextureCubeBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('usamplercube_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, -1.01, 0.0], [1.0, 1.0, -1.01, 0.0],    true,    -2.0,    2.0,    false, [0, 0, 0],    texCubeMipmapUint, es3fShaderTextureFunctionTests.evalTextureCubeBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DArrayFixed, es3fShaderTextureFunctionTests.evalTexture2DArray, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DArrayMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DArray, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DArrayFloat, es3fShaderTextureFunctionTests.evalTexture2DArray, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DArrayMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DArray, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DArrayInt, es3fShaderTextureFunctionTests.evalTexture2DArray, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DArrayMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DArray, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DArrayUint, es3fShaderTextureFunctionTests.evalTexture2DArray, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DArrayMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DArray, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_bias_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    true,    -2.0,    2.0,    false, [0, 0, 0],    tex2DArrayMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DArrayBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_bias_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    true,    -2.0,    2.0,    false, [0, 0, 0],    tex2DArrayMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DArrayBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2darray_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    true,    -2.0,    2.0,    false, [0, 0, 0],    tex2DArrayMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DArrayBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2darray_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    true,    -2.0,    2.0,    false, [0, 0, 0],    tex2DArrayMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DArrayBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex3DFixed, es3fShaderTextureFunctionTests.evalTexture3D, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex3DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture3D, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex3DFloat, es3fShaderTextureFunctionTests.evalTexture3D, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3D, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex3DInt, es3fShaderTextureFunctionTests.evalTexture3D, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex3DMipmapInt, es3fShaderTextureFunctionTests.evalTexture3D, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex3DUint, es3fShaderTextureFunctionTests.evalTexture3D, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3D, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_bias_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    true,    -2.0,    1.0,    false, [0, 0, 0],    tex3DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture3DBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_bias_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    true,    -2.0,    1.0,    false, [0, 0, 0],    tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler3d_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    true,    -2.0,    2.0,    false, [0, 0, 0],    tex3DMipmapInt, es3fShaderTextureFunctionTests.evalTexture3DBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler3d_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    true,    -2.0,    2.0,    false, [0, 0, 0],    tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 1.0, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DShadow, es3fShaderTextureFunctionTests.evalTexture2DShadow, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 1.0, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadow, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 1.0, 0.0],    true,    -2.0,    2.0,    false, [0, 0, 0],    tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getCaseSpec('samplercubeshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, 1.01, 0.0], [1.0, 1.0, 1.01, 1.0],    false,    0.0,    0.0,    false, [0, 0, 0],    texCubeShadow, es3fShaderTextureFunctionTests.evalTextureCubeShadow, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('samplercubeshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, 1.01, 0.0], [1.0, 1.0, 1.01, 1.0],    false,    0.0,    0.0,    false, [0, 0, 0],    texCubeMipmapShadow, es3fShaderTextureFunctionTests.evalTextureCubeShadow, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('samplercubeshadow_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.0, -1.0, 1.01, 0.0], [1.0, 1.0, 1.01, 1.0],    true,    -2.0,    2.0,    false, [0, 0, 0],    texCubeMipmapShadow, es3fShaderTextureFunctionTests.evalTextureCubeShadowBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler2darrayshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 1.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DArrayShadow, es3fShaderTextureFunctionTests.evalTexture2DArrayShadow, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2darrayshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 1.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DArrayMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DArrayShadow,        es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT)

                // Not in spec.
                // es3fShaderTextureFunctionTests.getCaseSpec('sampler2darrayshadow_bias',    (es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 1.0],    true,    -2.0,    2.0,    Vec2(0.0),    Vec2(0.0), false, [0, 0, 0]),    tex2DArrayMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DArrayShadowBias,    FRAGMENT)
            ];
            es3fShaderTextureFunctionTests.createCaseGroup(this, 'texture', 'texture() Tests', textureCases);

            // textureOffset() cases
            // \note _bias variants are not using mipmap thanks to wide allowed range for LOD computation
            /** @type {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} */ var textureOffsetCases = [
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    false,    0.0,    0.0,    true, [-8, 7, 0],    tex2DFixed, es3fShaderTextureFunctionTests.evalTexture2DOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    false,    0.0,    0.0,    true, [7, -8, 0],    tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    false,    0.0,    0.0,    true, [-8, 7, 0],    tex2DFloat, es3fShaderTextureFunctionTests.evalTexture2DOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    false,    0.0,    0.0,    true, [7, -8, 0],    tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    false,    0.0,    0.0,    true, [-8, 7, 0],    tex2DInt, es3fShaderTextureFunctionTests.evalTexture2DOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    false,    0.0,    0.0,    true, [7, -8, 0],    tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    false,    0.0,    0.0,    true, [-8, 7, 0],    tex2DUint, es3fShaderTextureFunctionTests.evalTexture2DOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    false,    0.0,    0.0,    true, [7, -8, 0],    tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_bias_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    true,    -2.0,    2.0,    true, [-8, 7, 0],    tex2DFixed, es3fShaderTextureFunctionTests.evalTexture2DOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_bias_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    true,    -2.0,    2.0,    true, [7, -8, 0],    tex2DFloat, es3fShaderTextureFunctionTests.evalTexture2DOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    true,    -2.0,    2.0,    true, [-8, 7, 0],    tex2DInt, es3fShaderTextureFunctionTests.evalTexture2DOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    true,    -2.0,    2.0,    true, [7, -8, 0],    tex2DUint, es3fShaderTextureFunctionTests.evalTexture2DOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    false,    0.0,    0.0,    true, [-8, 7, 0],    tex2DArrayFixed, es3fShaderTextureFunctionTests.evalTexture2DArrayOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    false,    0.0,    0.0,    true, [7, -8, 0],    tex2DArrayMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DArrayOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    false,    0.0,    0.0,    true, [-8, 7, 0],    tex2DArrayFloat, es3fShaderTextureFunctionTests.evalTexture2DArrayOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    false,    0.0,    0.0,    true, [7, -8, 0],    tex2DArrayMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DArrayOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    false,    0.0,    0.0,    true, [-8, 7, 0],    tex2DArrayInt, es3fShaderTextureFunctionTests.evalTexture2DArrayOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    false,    0.0,    0.0,    true, [7, -8, 0],    tex2DArrayMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DArrayOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    false,    0.0,    0.0,    true, [-8, 7, 0],    tex2DArrayUint, es3fShaderTextureFunctionTests.evalTexture2DArrayOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    false,    0.0,    0.0,    true, [7, -8, 0],    tex2DArrayMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DArrayOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_bias_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    true,    -2.0,    2.0,    true, [-8, 7, 0],    tex2DArrayFixed, es3fShaderTextureFunctionTests.evalTexture2DArrayOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_bias_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    true,    -2.0,    2.0,    true, [7, -8, 0],    tex2DArrayFloat, es3fShaderTextureFunctionTests.evalTexture2DArrayOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2darray_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    true,    -2.0,    2.0,    true, [-8, 7, 0],    tex2DArrayInt, es3fShaderTextureFunctionTests.evalTexture2DArrayOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2darray_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    true,    -2.0,    2.0,    true, [7, -8, 0],    tex2DArrayUint, es3fShaderTextureFunctionTests.evalTexture2DArrayOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    false,    0.0,    0.0,    true, [-8, 7, 3],    tex3DFixed, es3fShaderTextureFunctionTests.evalTexture3DOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    false,    0.0,    0.0,    true, [7, 3, -8],    tex3DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture3DOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    false,    0.0,    0.0,    true, [3, -8, 7],    tex3DFloat, es3fShaderTextureFunctionTests.evalTexture3DOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    false,    0.0,    0.0,    true, [-8, 7, 3],    tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    false,    0.0,    0.0,    true, [7, 3, -8],    tex3DInt, es3fShaderTextureFunctionTests.evalTexture3DOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    false,    0.0,    0.0,    true, [3, -8, 7],    tex3DMipmapInt, es3fShaderTextureFunctionTests.evalTexture3DOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    false,    0.0,    0.0,    true, [-8, 7, 3],    tex3DUint, es3fShaderTextureFunctionTests.evalTexture3DOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    false,    0.0,    0.0,    true, [7, 3, -8],    tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_bias_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    true,    -2.0,    1.0,    true, [-8, 7, 3],    tex3DFixed, es3fShaderTextureFunctionTests.evalTexture3DOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_bias_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    true,    -2.0,    1.0,    true, [7, 3, -8],    tex3DFloat, es3fShaderTextureFunctionTests.evalTexture3DOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler3d_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    true,    -2.0,    2.0,    true, [3, -8, 7],    tex3DInt, es3fShaderTextureFunctionTests.evalTexture3DOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler3d_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    true,    -2.0,    2.0,    true, [-8, 7, 3],    tex3DUint, es3fShaderTextureFunctionTests.evalTexture3DOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 1.0, 0.0],    false,    0.0,    0.0,    true, [-8, 7, 0],    tex2DShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 1.0, 0.0],    false,    0.0,    0.0,    true, [7, -8, 0],    tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTURE, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 1.0, 0.0],    true,    -2.0,    2.0,    true, [-8, 7, 0],    tex2DShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowOffsetBias,    es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT)
            ];
            es3fShaderTextureFunctionTests.createCaseGroup(this, 'textureoffset', 'textureOffset() Tests', textureOffsetCases);

            // textureProj() cases
            // \note Currently uses constant divider!
            /** @type {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} */ var textureProjCases = [
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DFixed, es3fShaderTextureFunctionTests.evalTexture2DProj3, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DProj3, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DFloat, es3fShaderTextureFunctionTests.evalTexture2DProj3, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DProj3, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DInt, es3fShaderTextureFunctionTests.evalTexture2DProj3, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DProj3, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DUint, es3fShaderTextureFunctionTests.evalTexture2DProj3, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DProj3, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_bias_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    true,    -2.0,    2.0,    false, [0, 0, 0],    tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DProj3Bias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_bias_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    true,    -2.0,    2.0,    false, [0, 0, 0],    tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DProj3Bias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec3_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    true,    -2.0,    2.0,    false, [0, 0, 0],    tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DProj3Bias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec3_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    true,    -2.0,    2.0,    false, [0, 0, 0],    tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DProj3Bias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DFixed, es3fShaderTextureFunctionTests.evalTexture2DProj, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DProj, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DFloat, es3fShaderTextureFunctionTests.evalTexture2DProj, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DProj, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DInt, es3fShaderTextureFunctionTests.evalTexture2DProj, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DProj, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DUint, es3fShaderTextureFunctionTests.evalTexture2DProj, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DProj, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_bias_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    true,    -2.0,    2.0,    false, [0, 0, 0],    tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DProjBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_bias_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    true,    -2.0,    2.0,    false, [0, 0, 0],    tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DProjBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec4_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    true,    -2.0,    2.0,    false, [0, 0, 0],    tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DProjBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec4_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    true,    -2.0,    2.0,    false, [0, 0, 0],    tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DProjBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    false,    0.0,    0.0,    false, [0, 0, 0],    tex3DFixed, es3fShaderTextureFunctionTests.evalTexture3DProj, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    false,    0.0,    0.0,    false, [0, 0, 0],    tex3DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture3DProj, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    false,    0.0,    0.0,    false, [0, 0, 0],    tex3DFloat, es3fShaderTextureFunctionTests.evalTexture3DProj, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    false,    0.0,    0.0,    false, [0, 0, 0],    tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DProj, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    false,    0.0,    0.0,    false, [0, 0, 0],    tex3DInt, es3fShaderTextureFunctionTests.evalTexture3DProj, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    false,    0.0,    0.0,    false, [0, 0, 0],    tex3DMipmapInt, es3fShaderTextureFunctionTests.evalTexture3DProj, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    false,    0.0,    0.0,    false, [0, 0, 0],    tex3DUint, es3fShaderTextureFunctionTests.evalTexture3DProj, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    false,    0.0,    0.0,    false, [0, 0, 0],    tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DProj, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_bias_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    true,    -2.0,    1.0,    false, [0, 0, 0],    tex3DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture3DProjBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_bias_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    true,    -2.0,    1.0,    false, [0, 0, 0],    tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DProjBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler3d_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    true,    -2.0,    2.0,    false, [0, 0, 0],    tex3DMipmapInt, es3fShaderTextureFunctionTests.evalTexture3DProjBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler3d_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    true,    -2.0,    2.0,    false, [0, 0, 0],    tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DProjBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.2, 0.6, 0.0, 1.5], [-2.25, -3.45, 1.5, 1.5],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowProj, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.2, 0.6, 0.0, 1.5], [-2.25, -3.45, 1.5, 1.5],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowProj, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.2, 0.6, 0.0, 1.5], [-2.25, -3.45, 1.5, 1.5],    true,    -2.0,    2.0,    false, [0, 0, 0],    tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowProjBias,    es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT)
            ];
            es3fShaderTextureFunctionTests.createCaseGroup(this, 'textureproj', 'textureProj() Tests', textureProjCases);

            // textureProjOffset() cases
            // \note Currently uses constant divider!
            /** @type {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} */ var textureProjOffsetCases = [
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    false,    0.0,    0.0,    true, [-8, 7, 0],    tex2DFixed, es3fShaderTextureFunctionTests.evalTexture2DProj3Offset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    false,    0.0,    0.0,    true, [7, -8, 0],    tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DProj3Offset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    false,    0.0,    0.0,    true, [-8, 7, 0],    tex2DFloat, es3fShaderTextureFunctionTests.evalTexture2DProj3Offset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    false,    0.0,    0.0,    true, [7, -8, 0],    tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DProj3Offset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    false,    0.0,    0.0,    true, [-8, 7, 0],    tex2DInt, es3fShaderTextureFunctionTests.evalTexture2DProj3Offset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    false,    0.0,    0.0,    true, [7, -8, 0],    tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DProj3Offset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    false,    0.0,    0.0,    true, [-8, 7, 0],    tex2DUint, es3fShaderTextureFunctionTests.evalTexture2DProj3Offset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    false,    0.0,    0.0,    true, [7, -8, 0],    tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DProj3Offset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_bias_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    true,    -2.0,    2.0,    true, [-8, 7, 0],    tex2DFixed, es3fShaderTextureFunctionTests.evalTexture2DProj3OffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_bias_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    true,    -2.0,    2.0,    true, [7, -8, 0],    tex2DFloat, es3fShaderTextureFunctionTests.evalTexture2DProj3OffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec3_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    true,    -2.0,    2.0,    true, [-8, 7, 0],    tex2DInt, es3fShaderTextureFunctionTests.evalTexture2DProj3OffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec3_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    true,    -2.0,    2.0,    true, [7, -8, 0],    tex2DUint, es3fShaderTextureFunctionTests.evalTexture2DProj3OffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    false,    0.0,    0.0,    true, [-8, 7, 0],    tex2DFixed, es3fShaderTextureFunctionTests.evalTexture2DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    false,    0.0,    0.0,    true, [7, -8, 0],    tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    false,    0.0,    0.0,    true, [-8, 7, 0],    tex2DFloat, es3fShaderTextureFunctionTests.evalTexture2DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    false,    0.0,    0.0,    true, [7, -8, 0],    tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    false,    0.0,    0.0,    true, [-8, 7, 0],    tex2DInt, es3fShaderTextureFunctionTests.evalTexture2DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    false,    0.0,    0.0,    true, [7, -8, 0],    tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    false,    0.0,    0.0,    true, [-8, 7, 0],    tex2DUint, es3fShaderTextureFunctionTests.evalTexture2DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    false,    0.0,    0.0,    true, [7, -8, 0],    tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_bias_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    true,    -2.0,    2.0,    true, [-8, 7, 0],    tex2DFixed, es3fShaderTextureFunctionTests.evalTexture2DProjOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_bias_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    true,    -2.0,    2.0,    true, [7, -8, 0],    tex2DFloat, es3fShaderTextureFunctionTests.evalTexture2DProjOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec4_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    true,    -2.0,    2.0,    true, [-8, 7, 0],    tex2DInt, es3fShaderTextureFunctionTests.evalTexture2DProjOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec4_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    true,    -2.0,    2.0,    true, [7, -8, 0],    tex2DUint, es3fShaderTextureFunctionTests.evalTexture2DProjOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    false,    0.0,    0.0,    true, [-8, 7, 3],    tex3DFixed, es3fShaderTextureFunctionTests.evalTexture3DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    false,    0.0,    0.0,    true, [7, 3, -8],    tex3DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture3DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    false,    0.0,    0.0,    true, [3, -8, 7],    tex3DFloat, es3fShaderTextureFunctionTests.evalTexture3DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    false,    0.0,    0.0,    true, [-8, 7, 3],    tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    false,    0.0,    0.0,    true, [7, 3, -8],    tex3DInt, es3fShaderTextureFunctionTests.evalTexture3DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    false,    0.0,    0.0,    true, [3, -8, 7],    tex3DMipmapInt, es3fShaderTextureFunctionTests.evalTexture3DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    false,    0.0,    0.0,    true, [-8, 7, 3],    tex3DUint, es3fShaderTextureFunctionTests.evalTexture3DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    false,    0.0,    0.0,    true, [7, 3, -8],    tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DProjOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_bias_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    true,    -2.0,    2.0,    true, [-8, 7, 3],    tex3DFixed, es3fShaderTextureFunctionTests.evalTexture3DProjOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_bias_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    true,    -2.0,    2.0,    true, [7, 3, -8],    tex3DFloat, es3fShaderTextureFunctionTests.evalTexture3DProjOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler3d_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    true,    -2.0,    2.0,    true, [3, -8, 7],    tex3DInt, es3fShaderTextureFunctionTests.evalTexture3DProjOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler3d_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    true,    -2.0,    2.0,    true, [-8, 7, 3],    tex3DUint, es3fShaderTextureFunctionTests.evalTexture3DProjOffsetBias, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                // NOTE: offset changed from [-8, 7, 0] in native dEQP to [7, -8, 0] per https://github.com/KhronosGroup/WebGL/issues/2033
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.2, 0.6, 0.0, 1.5], [-2.25, -3.45, 1.5, 1.5],    false,    0.0,    0.0,    true, [7, -8, 0],    tex2DShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowProjOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.2, 0.6, 0.0, 1.5], [-2.25, -3.45, 1.5, 1.5],    false,    0.0,    0.0,    true, [7, -8, 0],    tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowProjOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow_bias', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJ, [0.2, 0.6, 0.0, 1.5], [-2.25, -3.45, 1.5, 1.5],    true,    -2.0,    2.0,    true, [-8, 7, 0],    tex2DShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowProjOffsetBias,    es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT)
            ];
            es3fShaderTextureFunctionTests.createCaseGroup(this, 'textureprojoffset', 'textureOffsetProj() Tests', textureProjOffsetCases);

            // textureLod() cases
            /** @type {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} */ var textureLodCases = [
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    false,    -1.0,    9.0,    false, [0, 0, 0],    tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    false,    -1.0,    9.0,    false, [0, 0, 0],    tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    false,    -1.0,    9.0,    false, [0, 0, 0],    tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    false,    -1.0,    9.0,    false, [0, 0, 0],    tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),

                es3fShaderTextureFunctionTests.getCaseSpec('samplercube_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.0, -1.0, 1.01, 0.0], [1.0, 1.0, 1.01, 0.0],    false,    -1.0,    9.0,    false, [0, 0, 0],    texCubeMipmapFixed, es3fShaderTextureFunctionTests.evalTextureCubeLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('samplercube_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.0, -1.0, -1.01, 0.0], [1.0, 1.0, -1.01, 0.0],    false,    -1.0,    9.0,    false, [0, 0, 0],    texCubeMipmapFloat, es3fShaderTextureFunctionTests.evalTextureCubeLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('isamplercube', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.0, -1.0, 1.01, 0.0], [1.0, 1.0, 1.01, 0.0],    false,    -1.0,    9.0,    false, [0, 0, 0],    texCubeMipmapInt, es3fShaderTextureFunctionTests.evalTextureCubeLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('usamplercube', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.0, -1.0, -1.01, 0.0], [1.0, 1.0, -1.01, 0.0],    false,    -1.0,    9.0,    false, [0, 0, 0],    texCubeMipmapUint, es3fShaderTextureFunctionTests.evalTextureCubeLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    false,    -1.0,    8.0,    false, [0, 0, 0],    tex2DArrayMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DArrayLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    false,    -1.0,    8.0,    false, [0, 0, 0],    tex2DArrayMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DArrayLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    false,    -1.0,    8.0,    false, [0, 0, 0],    tex2DArrayMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DArrayLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    false,    -1.0,    8.0,    false, [0, 0, 0],    tex2DArrayMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DArrayLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    false,    -1.0,    7.0,    false, [0, 0, 0],    tex3DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture3DLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    false,    -1.0,    7.0,    false, [0, 0, 0],    tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    false,    -1.0,    7.0,    false, [0, 0, 0],    tex3DMipmapInt, es3fShaderTextureFunctionTests.evalTexture3DLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    false,    -1.0,    7.0,    false, [0, 0, 0],    tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 1.0, 0.0],    false,    -1.0,    9.0,    false, [0, 0, 0],    tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowLod,    es3fShaderTextureFunctionTests.CaseFlags.BOTH)
            ];
            es3fShaderTextureFunctionTests.createCaseGroup(this, 'texturelod', 'textureLod() Tests', textureLodCases);

            // textureLodOffset() cases
            /** @type {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} */ var textureLodOffsetCases = [
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    false,    -1.0,    9.0,    true, [-8, 7, 0],    tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    false,    -1.0,    9.0,    true, [7, -8, 0],    tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    false,    -1.0,    9.0,    true, [-8, 7, 0],    tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0],    false,    -1.0,    9.0,    true, [7, -8, 0],    tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    false,    -1.0,    8.0,    true, [-8, 7, 0],    tex2DArrayMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DArrayLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    false,    -1.0,    8.0,    true, [7, -8, 0],    tex2DArrayMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DArrayLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    false,    -1.0,    8.0,    true, [-8, 7, 0],    tex2DArrayMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DArrayLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0],    false,    -1.0,    8.0,    true, [7, -8, 0],    tex2DArrayMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DArrayLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    false,    -1.0,    7.0,    true, [-8, 7, 3],    tex3DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture3DLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    false,    -1.0,    7.0,    true, [7, 3, -8],    tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    false,    -1.0,    7.0,    true, [3, -8, 7],    tex3DMipmapInt, es3fShaderTextureFunctionTests.evalTexture3DLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0],    false,    -1.0,    7.0,    true, [-8, 7, 3],    tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTURELOD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 1.0, 0.0],    false,    -1.0,    9.0,    true, [-8, 7, 0],    tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowLodOffset,    es3fShaderTextureFunctionTests.CaseFlags.BOTH)
            ];
            es3fShaderTextureFunctionTests.createCaseGroup(this, 'texturelodoffset', 'textureLodOffset() Tests', textureLodOffsetCases);

            // textureProjLod() cases
            /** @type {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} */ var textureProjLodCases = [
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    false,    -1.0,    9.0,    false, [0, 0, 0],    tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DProjLod3, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    false,    -1.0,    9.0,    false, [0, 0, 0],    tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DProjLod3, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    false,    -1.0,    9.0,    false, [0, 0, 0],    tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DProjLod3, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    false,    -1.0,    9.0,    false, [0, 0, 0],    tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DProjLod3, es3fShaderTextureFunctionTests.CaseFlags.BOTH),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    false,    -1.0,    9.0,    false, [0, 0, 0],    tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DProjLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    false,    -1.0,    9.0,    false, [0, 0, 0],    tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DProjLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    false,    -1.0,    9.0,    false, [0, 0, 0],    tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DProjLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    false,    -1.0,    9.0,    false, [0, 0, 0],    tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DProjLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    false,    -1.0,    7.0,    false, [0, 0, 0],    tex3DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture3DProjLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    false,    -1.0,    7.0,    false, [0, 0, 0],    tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DProjLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    false,    -1.0,    7.0,    false, [0, 0, 0],    tex3DMipmapInt, es3fShaderTextureFunctionTests.evalTexture3DProjLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    false,    -1.0,    7.0,    false, [0, 0, 0],    tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DProjLod, es3fShaderTextureFunctionTests.CaseFlags.BOTH),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [0.2, 0.6, 0.0, 1.5], [-2.25, -3.45, 1.5, 1.5],    false,    -1.0,    9.0,    false, [0, 0, 0],    tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowProjLod,    es3fShaderTextureFunctionTests.CaseFlags.BOTH)
            ];
            es3fShaderTextureFunctionTests.createCaseGroup(this, 'textureprojlod', 'textureProjLod() Tests', textureProjLodCases);

            // textureProjLodOffset() cases
            /** @type {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} */ var textureProjLodOffsetCases = [
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    false,    -1.0,    9.0,    true, [-8, 7, 0],    tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DProjLod3Offset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec3_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    false,    -1.0,    9.0,    true, [7, -8, 0],    tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DProjLod3Offset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    false,    -1.0,    9.0,    true, [-8, 7, 0],    tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DProjLod3Offset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0],    false,    -1.0,    9.0,    true, [7, -8, 0],    tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DProjLod3Offset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    false,    -1.0,    9.0,    true, [-8, 7, 0],    tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DProjLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_vec4_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    false,    -1.0,    9.0,    true, [7, -8, 0],    tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DProjLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    false,    -1.0,    9.0,    true, [-8, 7, 0],    tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DProjLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5],    false,    -1.0,    9.0,    true, [7, -8, 0],    tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DProjLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    false,    -1.0,    7.0,    true, [-8, 7, 3],    tex3DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture3DProjLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    false,    -1.0,    7.0,    true, [7, 3, -8],    tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DProjLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    false,    -1.0,    7.0,    true, [3, -8, 7],    tex3DMipmapInt, es3fShaderTextureFunctionTests.evalTexture3DProjLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75],    false,    -1.0,    7.0,    true, [-8, 7, 3],    tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DProjLodOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJLOD, [0.2, 0.6, 0.0, 1.5], [-2.25, -3.45, 1.5, 1.5],    false,    -1.0,    9.0,    true, [-8, 7, 0],    tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowProjLodOffset,    es3fShaderTextureFunctionTests.CaseFlags.BOTH)
            ];
            es3fShaderTextureFunctionTests.createCaseGroup(this, 'textureprojlodoffset', 'textureProjLodOffset() Tests', textureProjLodOffsetCases);

            // textureGrad() cases
            // \note Only one of dudx, dudy, dvdx, dvdy is non-zero since spec allows approximating p from derivates by various methods.
            /** @type {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} */ var textureGradCases = [
                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    false, [0, 0, 0],    tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    false, [0, 0, 0],    tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('isampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [-0.2, 0.0, 0.0],    false, [0, 0, 0],    tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('usampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0],    false, [0, 0, 0],    tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),

                es3fShaderTextureFunctionTests.getGradCaseSpec('samplercube_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.0, -1.0, 1.01, 0.0], [1.0, 1.0, 1.01, 0.0], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    false, [0, 0, 0],    texCubeMipmapFixed, es3fShaderTextureFunctionTests.evalTextureCubeGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('samplercube_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.0, -1.0, -1.01, 0.0], [1.0, 1.0, -1.01, 0.0], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    false, [0, 0, 0],    texCubeMipmapFloat, es3fShaderTextureFunctionTests.evalTextureCubeGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('isamplercube', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.0, -1.0, 1.01, 0.0], [1.0, 1.0, 1.01, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [-0.2, 0.0, 0.0],    false, [0, 0, 0],    texCubeMipmapInt, es3fShaderTextureFunctionTests.evalTextureCubeGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('usamplercube', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.0, -1.0, -1.01, 0.0], [1.0, 1.0, -1.01, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0],    false, [0, 0, 0],    texCubeMipmapUint, es3fShaderTextureFunctionTests.evalTextureCubeGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),

                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2darray_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    false, [0, 0, 0],    tex2DArrayMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DArrayGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2darray_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    false, [0, 0, 0],    tex2DArrayMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DArrayGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('isampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [-0.2, 0.0, 0.0],    false, [0, 0, 0],    tex2DArrayMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DArrayGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('usampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0],    false, [0, 0, 0],    tex2DArrayMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DArrayGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),

                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    false, [0, 0, 0],    tex3DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture3DGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    false, [0, 0, 0],    tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DGrad, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.2], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    false, [0, 0, 0],    tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DGrad, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getGradCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [-0.2, 0.0, 0.0],    false, [0, 0, 0],    tex3DMipmapInt, es3fShaderTextureFunctionTests.evalTexture3DGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0],    false, [0, 0, 0],    tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DGrad, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getGradCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, -0.2],    false, [0, 0, 0],    tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DGrad, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 1.0, 0.0], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    false, [0, 0, 0],    tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('samplercubeshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.0, -1.0, 1.01, 0.0], [1.0, 1.0, 1.01, 1.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    false, [0, 0, 0],    texCubeMipmapShadow, es3fShaderTextureFunctionTests.evalTextureCubeShadowGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2darrayshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 1.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0],    false, [0, 0, 0],    tex2DArrayMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DArrayShadowGrad, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2darrayshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 1.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0],    false, [0, 0, 0],    tex2DArrayMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DArrayShadowGrad, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT)
            ];
            es3fShaderTextureFunctionTests.createCaseGroup(this, 'texturegrad', 'textureGrad() Tests', textureGradCases);

            // textureGradOffset() cases
            /** @type {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} */ var textureGradOffsetCases = [
                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    true, [-8, 7, 0],    tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    true, [7, -8, 0],    tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('isampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [-0.2, 0.0, 0.0],    true, [-8, 7, 0],    tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('usampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0],    true, [7, -8, 0],    tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),

                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2darray_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    true, [-8, 7, 0],    tex2DArrayMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DArrayGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2darray_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    true, [7, -8, 0],    tex2DArrayMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DArrayGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('isampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [-0.2, 0.0, 0.0],    true, [-8, 7, 0],    tex2DArrayMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DArrayGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('usampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0],    true, [7, -8, 0],    tex2DArrayMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DArrayGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),

                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    true, [-8, 7, 3],    tex3DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture3DGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    true, [7, 3, -8],    tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DGradOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.2], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    true, [3, -8, 7],    tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DGradOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getGradCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [-0.2, 0.0, 0.0],    true, [-8, 7, 3],    tex3DMipmapInt, es3fShaderTextureFunctionTests.evalTexture3DGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0],    true, [7, 3, -8],    tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DGradOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getGradCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -1.4, 0.1, 0.0], [1.5, 2.3, 2.3, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, -0.2],    true, [3, -8, 7],    tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DGradOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 1.0, 0.0], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    true, [-8, 7, 0],    tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowGradOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-0.2, -0.4, 0.0, 0.0], [1.5, 2.3, 1.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    true, [7, -8, 0],    tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowGradOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2darrayshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 1.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0],    true, [-8, 7, 0],    tex2DArrayMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DArrayShadowGradOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2darrayshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREGRAD, [-1.2, -0.4, -0.5, 0.0], [1.5, 2.3, 3.5, 1.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0],    true, [7, -8, 0],    tex2DArrayMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DArrayShadowGradOffset,    es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT)
            ];
            es3fShaderTextureFunctionTests.createCaseGroup(this, 'texturegradoffset', 'textureGradOffset() Tests', textureGradOffsetCases);

            // textureProjGrad() cases
            /** @type {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} */ var textureProjGradCases = [
                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2d_vec3_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    false, [0, 0, 0],    tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DProjGrad3, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2d_vec3_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    false, [0, 0, 0],    tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DProjGrad3, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('isampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [-0.2, 0.0, 0.0],    false, [0, 0, 0],    tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DProjGrad3, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('usampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0],    false, [0, 0, 0],    tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DProjGrad3, es3fShaderTextureFunctionTests.CaseFlags.BOTH),

                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2d_vec4_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    false, [0, 0, 0],    tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DProjGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2d_vec4_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    false, [0, 0, 0],    tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DProjGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('isampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [-0.2, 0.0, 0.0],    false, [0, 0, 0],    tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DProjGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('usampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0],    false, [0, 0, 0],    tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DProjGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),

                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    false, [0, 0, 0],    tex3DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture3DProjGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    false, [0, 0, 0],    tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DProjGrad, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], [0.0, 0.0, 0.0], [0.0, 0.0, 0.2], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    false, [0, 0, 0],    tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DProjGrad, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getGradCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [-0.2, 0.0, 0.0],    false, [0, 0, 0],    tex3DMipmapInt, es3fShaderTextureFunctionTests.evalTexture3DProjGrad, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0],    false, [0, 0, 0],    tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DProjGrad, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getGradCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, -0.2],    false, [0, 0, 0],    tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DProjGrad, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.2, 0.6, 0.0, -1.5], [-2.25, -3.45, -1.5, -1.5], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    false, [0, 0, 0],    tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowProjGrad, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.2, 0.6, 0.0, -1.5], [-2.25, -3.45, -1.5, -1.5], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0],    false, [0, 0, 0],    tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowProjGrad,    es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT)
            ];
            es3fShaderTextureFunctionTests.createCaseGroup(this, 'textureprojgrad', 'textureProjGrad() Tests', textureProjGradCases);

            // textureProjGradOffset() cases
            /** @type {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} */ var textureProjGradOffsetCases = [
                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2d_vec3_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    true, [-8, 7, 0],    tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DProjGrad3Offset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2d_vec3_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    true, [7, -8, 0],    tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DProjGrad3Offset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('isampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [-0.2, 0.0, 0.0],    true, [-8, 7, 0],    tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DProjGrad3Offset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('usampler2d_vec3', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD3, [-0.3, -0.6, 1.5, 0.0], [2.25, 3.45, 1.5, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0],    true, [7, -8, 0],    tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DProjGrad3Offset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),

                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2d_vec4_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    true, [-8, 7, 0],    tex2DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture2DProjGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2d_vec4_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    true, [7, -8, 0],    tex2DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture2DProjGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('isampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [-0.2, 0.0, 0.0],    true, [-8, 7, 0],    tex2DMipmapInt, es3fShaderTextureFunctionTests.evalTexture2DProjGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('usampler2d_vec4', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [-0.3, -0.6, 0.0, 1.5], [2.25, 3.45, 0.0, 1.5], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0],    true, [7, -8, 0],    tex2DMipmapUint, es3fShaderTextureFunctionTests.evalTexture2DProjGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),

                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    true, [-8, 7, 3],    tex3DMipmapFixed, es3fShaderTextureFunctionTests.evalTexture3DProjGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    true, [7, 3, -8],    tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DProjGradOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], [0.0, 0.0, 0.0], [0.0, 0.0, 0.2], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    true, [3, -8, 7],    tex3DMipmapFloat, es3fShaderTextureFunctionTests.evalTexture3DProjGradOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),
                es3fShaderTextureFunctionTests.getGradCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [-0.2, 0.0, 0.0],    true, [-8, 7, 3],    tex3DMipmapInt, es3fShaderTextureFunctionTests.evalTexture3DProjGradOffset, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getGradCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.2, 0.0],    true, [7, 3, -8],    tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DProjGradOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getGradCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.9, 1.05, -0.08, -0.75], [-1.13, -1.7, -1.7, -0.75], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, -0.2],    true, [3, -8, 7],    tex3DMipmapUint, es3fShaderTextureFunctionTests.evalTexture3DProjGradOffset, es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT),

                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.2, 0.6, 0.0, -1.5], [-2.25, -3.45, -1.5, -1.5], [0.0, 0.0, 0.0], [0.2, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],    true, [-8, 7, 0],    tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowProjGradOffset, es3fShaderTextureFunctionTests.CaseFlags.VERTEX),
                es3fShaderTextureFunctionTests.getGradCaseSpec('sampler2dshadow', es3fShaderTextureFunctionTests.TexFunction.TEXTUREPROJGRAD, [0.2, 0.6, 0.0, -1.5], [-2.25, -3.45, -1.5, -1.5], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, -0.2, 0.0],    true, [7, -8, 0],    tex2DMipmapShadow, es3fShaderTextureFunctionTests.evalTexture2DShadowProjGradOffset,    es3fShaderTextureFunctionTests.CaseFlags.FRAGMENT)
            ];
            es3fShaderTextureFunctionTests.createCaseGroup(this, 'textureprojgradoffset', 'textureProjGradOffset() Tests', textureProjGradOffsetCases);

            // texelFetch() cases
            // \note Level is constant across quad
            /** @type {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} */ var texelFetchCases = [
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [0.0, 0.0, 0.0, 0.0], [255.9, 255.9, 0.0, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DTexelFetchFixed, es3fShaderTextureFunctionTests.evalTexelFetch2D, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_float', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [0.0, 0.0, 0.0, 0.0], [127.9, 127.9, 0.0, 0.0],    false,    1.0,    1.0,    false, [0, 0, 0],    tex2DTexelFetchFloat, es3fShaderTextureFunctionTests.evalTexelFetch2D, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [0.0, 0.0, 0.0, 0.0], [63.9, 63.9, 0.0, 0.0],    false,    2.0,    2.0,    false, [0, 0, 0],    tex2DTexelFetchInt, es3fShaderTextureFunctionTests.evalTexelFetch2D, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [0.0, 0.0, 0.0, 0.0], [15.9, 15.9, 0.0, 0.0],    false,    4.0,    4.0,    false, [0, 0, 0],    tex2DTexelFetchUint, es3fShaderTextureFunctionTests.evalTexelFetch2D, es3fShaderTextureFunctionTests.CaseFlags.BOTH),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [0.0, 0.0, 0.0, 0.0], [127.9, 127.9, 3.9, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex2DArrayTexelFetchFixed, es3fShaderTextureFunctionTests.evalTexelFetch2DArray, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_float', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [0.0, 0.0, 0.0, 0.0], [63.9, 63.9, 3.9, 0.0],    false,    1.0,    1.0,    false, [0, 0, 0],    tex2DArrayTexelFetchFloat, es3fShaderTextureFunctionTests.evalTexelFetch2DArray, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [0.0, 0.0, 0.0, 0.0], [31.9, 31.9, 3.9, 0.0],    false,    2.0,    2.0,    false, [0, 0, 0],    tex2DArrayTexelFetchInt, es3fShaderTextureFunctionTests.evalTexelFetch2DArray, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [0.0, 0.0, 0.0, 0.0], [15.9, 15.9, 3.9, 0.0],    false,    3.0,    3.0,    false, [0, 0, 0],    tex2DArrayTexelFetchUint, es3fShaderTextureFunctionTests.evalTexelFetch2DArray, es3fShaderTextureFunctionTests.CaseFlags.BOTH),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [0.0, 0.0, 0.0, 0.0], [63.9, 31.9, 31.9, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex3DTexelFetchFixed, es3fShaderTextureFunctionTests.evalTexelFetch3D, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [0.0, 0.0, 0.0, 0.0], [31.9, 15.9, 15.9, 0.0],    false,    1.0,    1.0,    false, [0, 0, 0],    tex3DTexelFetchFloat, es3fShaderTextureFunctionTests.evalTexelFetch3D, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [0.0, 0.0, 0.0, 0.0], [15.9,  7.9,  7.9, 0.0],    false,    2.0,    2.0,    false, [0, 0, 0],    tex3DTexelFetchInt, es3fShaderTextureFunctionTests.evalTexelFetch3D, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [0.0, 0.0, 0.0, 0.0], [63.9, 31.9, 31.9, 0.0],    false,    0.0,    0.0,    false, [0, 0, 0],    tex3DTexelFetchUint, es3fShaderTextureFunctionTests.evalTexelFetch3D,        es3fShaderTextureFunctionTests.CaseFlags.BOTH)
            ];
            es3fShaderTextureFunctionTests.createCaseGroup(this, 'texelfetch', 'texelFetch() Tests', texelFetchCases);

            // texelFetchOffset() cases
            /** @type {Array<es3fShaderTextureFunctionTests.TexFuncCaseSpec>} */ var texelFetchOffsetCases = [
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [8.0, -7.0, 0.0, 0.0], [263.9, 248.9, 0.0, 0.0],    false,    0.0,    0.0,    true, [-8, 7, 0],    tex2DTexelFetchFixed, es3fShaderTextureFunctionTests.evalTexelFetch2D, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2d_float', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [-7.0, 8.0, 0.0, 0.0], [120.9, 135.9, 0.0, 0.0],    false,    1.0,    1.0,    true, [7, -8, 0],    tex2DTexelFetchFloat, es3fShaderTextureFunctionTests.evalTexelFetch2D, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [8.0, -7.0, 0.0, 0.0], [71.9, 56.9, 0.0, 0.0],    false,    2.0,    2.0,    true, [-8, 7, 0],    tex2DTexelFetchInt, es3fShaderTextureFunctionTests.evalTexelFetch2D, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2d', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [-7.0, 8.0, 0.0, 0.0], [8.9, 23.9, 0.0, 0.0],    false,    4.0,    4.0,    true, [7, -8, 0],    tex2DTexelFetchUint, es3fShaderTextureFunctionTests.evalTexelFetch2D, es3fShaderTextureFunctionTests.CaseFlags.BOTH),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [8.0, -7.0, 0.0, 0.0], [135.9, 120.9, 3.9, 0.0],    false,    0.0,    0.0,    true, [-8, 7, 0],    tex2DArrayTexelFetchFixed, es3fShaderTextureFunctionTests.evalTexelFetch2DArray, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler2darray_float', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [-7.0, 8.0, 0.0, 0.0], [56.9, 71.9, 3.9, 0.0],    false,    1.0,    1.0,    true, [7, -8, 0],    tex2DArrayTexelFetchFloat, es3fShaderTextureFunctionTests.evalTexelFetch2DArray, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [8.0, -7.0, 0.0, 0.0], [39.9, 24.9, 3.9, 0.0],    false,    2.0,    2.0,    true, [-8, 7, 0],    tex2DArrayTexelFetchInt, es3fShaderTextureFunctionTests.evalTexelFetch2DArray, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler2darray', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [-7.0, 8.0, 0.0, 0.0], [8.9, 23.9, 3.9, 0.0],    false,    3.0,    3.0,    true, [7, -8, 0],    tex2DArrayTexelFetchUint, es3fShaderTextureFunctionTests.evalTexelFetch2DArray, es3fShaderTextureFunctionTests.CaseFlags.BOTH),

                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_fixed', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [8.0, -7.0, -3.0, 0.0], [71.9, 24.9, 28.9, 0.0],    false,    0.0,    0.0,    true, [-8, 7, 3],    tex3DTexelFetchFixed, es3fShaderTextureFunctionTests.evalTexelFetch3D, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('sampler3d_float', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [-7.0, -3.0, 8.0, 0.0], [24.9, 12.9, 23.9, 0.0],    false,    1.0,    1.0,    true, [7, 3, -8],    tex3DTexelFetchFloat, es3fShaderTextureFunctionTests.evalTexelFetch3D, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('isampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [-3.0, 8.0, -7.0, 0.0], [12.9, 15.9,  0.9, 0.0],    false,    2.0,    2.0,    true, [3, -8, 7],    tex3DTexelFetchInt, es3fShaderTextureFunctionTests.evalTexelFetch3D, es3fShaderTextureFunctionTests.CaseFlags.BOTH),
                es3fShaderTextureFunctionTests.getCaseSpec('usampler3d', es3fShaderTextureFunctionTests.TexFunction.TEXELFETCH, [8.0, -7.0, -3.0, 0.0], [71.9, 24.9, 28.9, 0.0],    false,    0.0,    0.0,    true, [-8, 7, 3],    tex3DTexelFetchUint, es3fShaderTextureFunctionTests.evalTexelFetch3D,        es3fShaderTextureFunctionTests.CaseFlags.BOTH)
            ];
            es3fShaderTextureFunctionTests.createCaseGroup(this, 'texelfetchoffset', 'texelFetchOffset() Tests', texelFetchOffsetCases);

            // textureSize() cases
            /**
             * @struct
             * @constructor
             * @param  {string} name
             * @param  {string} samplerName
             * @param  {es3fShaderTextureFunctionTests.TextureSpec} textureSpec
             */
            var TextureSizeCaseSpec = function(name, samplerName, textureSpec) {
                /** @type {string} */ this.name = name;
                /** @type {string} */ this.samplerName = samplerName;
                /** @type {es3fShaderTextureFunctionTests.TextureSpec} */ this.textureSpec = textureSpec;
            };

            /** @type {Array<TextureSizeCaseSpec>} */ var  textureSizeCases = [
                new TextureSizeCaseSpec('sampler2d_fixed', 'sampler2D', tex2DFixed),
                new TextureSizeCaseSpec('sampler2d_float', 'sampler2D', tex2DFloat),
                new TextureSizeCaseSpec('isampler2d', 'isampler2D', tex2DInt),
                new TextureSizeCaseSpec('usampler2d', 'usampler2D', tex2DUint),
                new TextureSizeCaseSpec('sampler2dshadow', 'sampler2DShadow', tex2DShadow),
                new TextureSizeCaseSpec('sampler3d_fixed', 'sampler3D', tex3DFixed),
                new TextureSizeCaseSpec('sampler3d_float', 'sampler3D', tex3DFloat),
                new TextureSizeCaseSpec('isampler3d', 'isampler3D', tex3DInt),
                new TextureSizeCaseSpec('usampler3d', 'usampler3D', tex3DUint),
                new TextureSizeCaseSpec('samplercube_fixed', 'samplerCube', texCubeFixed),
                new TextureSizeCaseSpec('samplercube_float', 'samplerCube', texCubeFloat),
                new TextureSizeCaseSpec('isamplercube', 'isamplerCube', texCubeInt),
                new TextureSizeCaseSpec('usamplercube', 'usamplerCube', texCubeUint),
                new TextureSizeCaseSpec('samplercubeshadow', 'samplerCubeShadow', texCubeShadow),
                new TextureSizeCaseSpec('sampler2darray_fixed', 'sampler2DArray', tex2DArrayFixed),
                new TextureSizeCaseSpec('sampler2darray_float', 'sampler2DArray', tex2DArrayFloat),
                new TextureSizeCaseSpec('isampler2darray', 'isampler2DArray', tex2DArrayInt),
                new TextureSizeCaseSpec('usampler2darray', 'usampler2DArray', tex2DArrayUint),
                new TextureSizeCaseSpec('sampler2darrayshadow', 'sampler2DArrayShadow', tex2DArrayShadow)
            ];

            /** @type {tcuTestCase.DeqpTest} */ var group = tcuTestCase.newTest('texturesize', 'textureSize() Tests');
            testGroup.addChild(group);

            for (var ndx = 0; ndx < textureSizeCases.length; ++ndx) {
                group.addChild(new es3fShaderTextureFunctionTests.TextureSizeCase(textureSizeCases[ndx].name + '_vertex',  '', textureSizeCases[ndx].samplerName, textureSizeCases[ndx].textureSpec, true));
                group.addChild(new es3fShaderTextureFunctionTests.TextureSizeCase(textureSizeCases[ndx].name + '_fragment', '', textureSizeCases[ndx].samplerName, textureSizeCases[ndx].textureSpec, false));
            }

    };

    /**
    * Run test
    * @param {WebGL2RenderingContext} context
    * @param {Array<number>=} range Test range
    */
    es3fShaderTextureFunctionTests.run = function(context, range) {
        gl = context;

        const canvas = gl.canvas;
        canvas.width = canvasWH;
        canvas.height = canvasWH;

        //Set up Test Root parameters
        var state = tcuTestCase.runner;
        state.setRoot(new es3fShaderTextureFunctionTests.ShaderTextureFunctionTests());
        if (range)
            state.setRange(range);

        //Set up name and description of this test series.
        setCurrentTestName(state.testCases.fullName());
        description(state.testCases.getDescription());

        try {
            //Run test cases
            tcuTestCase.runTestCases();
        }
        catch (err) {
            testFailedOptions('Failed to es3fShaderTextureFunctionTests.run tests', false);
            tcuTestCase.runner.terminate();
        }
    };

});