Commit 64ce506d by Shahbaz Youssefi Committed by Angle LUCI CQ

Vulkan: SPIR-V Gen: Support most non-texture/image built-ins

Most GLSL built-ins map directly to some SPIR-V operation. texture*() and image*() built-ins are not implemented as well as a handful of other built-ins that require special-handling. Bug: angleproject:4889 Change-Id: I72abfb4692c3d66a3c8be43ce44ba6808efe6255 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2971646 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com>
parent b80f1377
{
"src/compiler/translator/ImmutableString_ESSL_autogen.cpp":
"a748e3105c8c85e2b4e1584a79404bd9",
"ad7e8eb7dc7e46acce2954c46a797432",
"src/compiler/translator/ImmutableString_autogen.cpp":
"e2ba7f03d436642b4e420442042cd09b",
"f570be6b24dca8759c8a5f8cfe229111",
"src/compiler/translator/Operator_autogen.h":
"ac52a4d3804c63ba14dde9c7f53d0460",
"8cc1f9b0fce0894ed4f8fee03723d5a4",
"src/compiler/translator/SymbolTable_ESSL_autogen.cpp":
"3fc55a91b8f90162a41cb5f5ecc83347",
"4de78590ff995146a34f0195e0b0026e",
"src/compiler/translator/SymbolTable_autogen.cpp":
"08e60b9de4a3bb5b491c11c014b3635b",
"15dc70a1fa62e42ac826e769b9dd8966",
"src/compiler/translator/SymbolTable_autogen.h":
"d43593050c4d1b31b0be9cdd3a2d0ea5",
"src/compiler/translator/builtin_function_declarations.txt":
"532f4ee284a113433fef303e38193334",
"0e5818ee65b5f06c0c21ddd578785fc9",
"src/compiler/translator/builtin_variables.json":
"0663a24c595b9221f44e3776337dec56",
"src/compiler/translator/gen_builtin_symbols.py":
"e0ed1f669f4e1c8fc3b1b7e9b40dbae4",
"src/compiler/translator/tree_util/BuiltIn_ESSL_autogen.h":
"62d779e93a9908279d97bddf4f6f163d",
"2cea05ebd1df1a1d297fff04c0d690a0",
"src/compiler/translator/tree_util/BuiltIn_complete_autogen.h":
"a93778687b24c0920990d68301253374",
"b60f08bb1c42131bda4f11ede17ebf23",
"src/tests/compiler_tests/ImmutableString_test_ESSL_autogen.cpp":
"5c8ac4ebc3234c51f37fdb5fb4480c33",
"a7ffe65463fee9d36d800e77c403ae9f",
"src/tests/compiler_tests/ImmutableString_test_autogen.cpp":
"54d439c54c4f9da58407af472c8c4a1d"
"41adf17de67b255b4e32485309dc6751"
}
\ No newline at end of file
......@@ -33,207 +33,207 @@ constexpr int mangledkT2[] = {243, 2806, 2646, 900, 1556, 238, 1079, 2379, 18
3034, 1339, 1962, 2836, 1405, 1808, 2356, 1708, 1616, 2555,
2384, 835, 1185, 1976, 1471, 1429, 2833, 3097, 1699, 752};
constexpr int mangledkG[] = {
0, 0, 0, 0, 0, 0, 0, 855, 969, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1644, 2907, 0, 405, 946, 0, 0, 1104, 0, 969, 508, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1376, 0, 0, 0, 0, 0, 0, 0,
0, 2630, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 2774, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2151, 0, 675, 0, 0, 0,
0, 0, 0, 0, 2606, 0, 1140, 1982, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 43, 1154, 0, 0, 0, 0, 2719, 963, 1401, 363, 0,
0, 0, 1483, 0, 0, 2838, 0, 0, 0, 123, 0, 2637, 0, 0, 0, 1236,
444, 252, 0, 1356, 756, 0, 0, 0, 0, 2619, 0, 321, 0, 0, 0, 0,
0, 0, 133, 0, 0, 0, 2604, 388, 0, 0, 0, 0, 0, 0, 0, 0,
1945, 0, 2090, 0, 0, 0, 0, 0, 196, 0, 0, 0, 47, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2965, 1013, 2305, 452,
0, 193, 549, 0, 0, 0, 0, 0, 96, 0, 0, 1848, 0, 3189, 0, 0,
1154, 0, 0, 2874, 0, 2297, 0, 0, 0, 3135, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1043, 0, 1450, 0, 0, 2821, 0, 3104, 819, 588, 0, 1938, 0,
0, 0, 370, 2518, 1986, 1323, 0, 1991, 1123, 0, 0, 1797, 0, 771, 639, 0,
2709, 1573, 0, 1912, 2052, 0, 0, 0, 974, 3139, 0, 2030, 2481, 0, 0, 1962,
138, 0, 0, 0, 0, 0, 901, 0, 743, 0, 2747, 0, 0, 231, 1597, 0,
1303, 0, 2024, 0, 0, 0, 737, 0, 0, 495, 0, 0, 0, 0, 1542, 611,
0, 931, 0, 473, 0, 0, 0, 172, 2730, 0, 0, 1885, 0, 989, 0, 0,
0, 229, 0, 392, 725, 1583, 0, 3057, 0, 2412, 0, 0, 0, 0, 0, 0,
1309, 2569, 0, 2881, 516, 938, 363, 3126, 2769, 0, 3188, 0, 0, 371, 215, 0,
1239, 0, 598, 0, 0, 0, 0, 1223, 1217, 0, 0, 0, 1672, 0, 0, 0,
698, 0, 0, 1312, 0, 2763, 0, 0, 1220, 1064, 0, 1607, 0, 0, 0, 0,
1277, 0, 0, 0, 0, 885, 0, 1619, 0, 689, 2999, 0, 0, 0, 0, 236,
0, 1099, 960, 0, 285, 1626, 0, 2138, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 673, 1940, 1604, 0, 0, 0, 0, 0, 0, 911, 538, 0, 0, 0,
605, 2958, 0, 0, 1604, 0, 0, 0, 0, 0, 0, 0, 287, 429, 1698, 0,
0, 0, 0, 1111, 0, 640, 1122, 3026, 0, 1379, 1185, 0, 0, 0, 757, 0,
0, 144, 0, 0, 3013, 0, 0, 0, 2992, 2171, 1137, 1474, 2298, 0, 405, 0,
0, 0, 1012, 0, 426, 0, 0, 0, 0, 141, 682, 0, 1762, 763, 1585, 0,
0, 0, 0, 0, 3201, 542, 482, 0, 0, 749, 588, 0, 0, 0, 0, 1392,
0, 377, 0, 0, 0, 2627, 0, 1923, 0, 0, 0, 0, 0, 2838, 678, 0,
0, 0, 2586, 0, 2498, 0, 783, 0, 0, 1074, 0, 0, 0, 0, 0, 0,
0, 2993, 328, 0, 0, 2725, 323, 0, 0, 0, 0, 0, 0, 0, 2952, 0,
879, 0, 0, 0, 0, 0, 1499, 0, 0, 2175, 1279, 0, 2322, 0, 0, 2438,
0, 184, 0, 125, 0, 0, 0, 1737, 0, 0, 2987, 165, 282, 850, 0, 88,
0, 2603, 0, 1069, 0, 0, 2857, 0, 0, 0, 929, 279, 460, 650, 0, 0,
0, 797, 0, 0, 0, 0, 0, 821, 0, 886, 284, 0, 0, 2650, 3009, 0,
0, 2533, 2638, 2146, 155, 1466, 1350, 2416, 0, 2455, 0, 0, 0, 0, 0, 987,
2649, 0, 1610, 0, 0, 0, 0, 1167, 62, 0, 588, 1092, 0, 0, 1220, 3141,
757, 0, 0, 2569, 0, 0, 2823, 2966, 0, 0, 228, 1309, 1953, 2116, 2267, 802,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 0, 3030, 3186, 376, 694,
0, 1191, 3157, 826, 0, 0, 0, 0, 0, 967, 0, 245, 571, 2888, 0, 0,
786, 1783, 148, 637, 0, 0, 1486, 0, 0, 426, 0, 0, 0, 0, 0, 3197,
2927, 0, 0, 0, 155, 2111, 0, 0, 1771, 1625, 0, 0, 0, 0, 0, 0,
2744, 1023, 1403, 2268, 867, 0, 0, 0, 0, 616, 0, 0, 258, 0, 259, 182,
834, 2251, 54, 0, 1124, 0, 0, 445, 0, 3198, 1848, 0, 0, 0, 750, 0,
0, 0, 0, 0, 695, 1103, 3085, 0, 0, 1016, 1090, 0, 151, 1358, 1369, 0,
0, 0, 0, 0, 3083, 2677, 2820, 0, 0, 0, 0, 634, 0, 2467, 0, 2565,
0, 0, 2056, 1294, 0, 1538, 0, 0, 1511, 2325, 0, 0, 25, 0, 0, 0,
145, 0, 2458, 0, 2015, 517, 354, 823, 0, 0, 0, 0, 0, 1265, 141, 2476,
0, 0, 0, 0, 1556, 184, 0, 0, 0, 0, 0, 1812, 134, 0, 1830, 0,
0, 968, 1037, 0, 792, 2673, 527, 0, 0, 2445, 0, 0, 0, 0, 686, 0,
0, 298, 1341, 0, 1020, 0, 0, 2045, 0, 0, 0, 0, 838, 329, 0, 2007,
1092, 1121, 1411, 0, 0, 0, 0, 2377, 593, 213, 645, 849, 2232, 149, 676, 0,
0, 0, 2902, 0, 1069, 1171, 892, 0, 416, 1281, 844, 0, 1081, 216, 397, 0,
0, 138, 0, 322, 2527, 341, 2158, 0, 0, 1665, 2991, 6, 1405, 0, 0, 0,
0, 0, 122, 394, 85, 0, 3201, 0, 447, 0, 0, 0, 679, 1489, 0, 2028,
0, 2969, 1982, 3143, 2732, 1053, 0, 0, 2745, 0, 346, 0, 1071, 0, 528, 1848,
0, 0, 879, 1929, 2839, 665, 0, 0, 282, 0, 0, 217, 0, 0, 632, 723,
960, 0, 0, 0, 45, 334, 1890, 2771, 0, 0, 0, 0, 1452, 3012, 0, 1797,
0, 0, 446, 0, 248, 3007, 421, 0, 0, 2754, 0, 2242, 0, 0, 1004, 0,
0, 0, 0, 223, 3169, 0, 0, 529, 0, 0, 2802, 0, 0, 0, 0, 1625,
0, 0, 2910, 324, 0, 2193, 1137, 3139, 0, 2970, 0, 1692, 2063, 1072, 1158, 0,
0, 0, 765, 0, 631, 364, 0, 0, 0, 281, 777, 0, 1757, 0, 0, 1692,
0, 192, 767, 0, 0, 451, 518, 0, 0, 0, 0, 3002, 1950, 0, 0, 200,
0, 0, 854, 179, 2666, 0, 294, 0, 2888, 3080, 2207, 0, 944, 0, 0, 0,
3072, 2662, 0, 0, 469, 256, 0, 0, 1339, 335, 0, 590, 600, 0, 998, 0,
0, 0, 0, 0, 0, 0, 548, 2769, 0, 0, 0, 2405, 2348, 0, 215, 0,
0, 0, 0, 0, 0, 0, 0, 612, 0, 0, 186, 210, 1350, 3104, 0, 54,
402, 1150, 712, 0, 107, 0, 0, 0, 410, 2389, 0, 117, 2046, 2890, 2434, 2449,
0, 729, 2658, 0, 0, 0, 2638, 0, 831, 512, 799, 0, 0, 0, 62, 0,
0, 1865, 1887, 766, 46, 0, 0, 0, 0, 34, 0, 0, 0, 174, 2001, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 462, 0, 0, 0, 0, 1548,
0, 0, 1069, 832, 0, 1358, 0, 0, 0, 0, 0, 0, 160, 539, 0, 0,
0, 0, 0, 304, 77, 0, 1532, 0, 0, 0, 278, 0, 0, 0, 0, 2794,
0, 0, 0, 0, 2434, 0, 0, 1492, 0, 0, 0, 2511, 0, 0, 0, 1046,
629, 0, 0, 0, 1037, 278, 0, 0, 0, 1507, 688, 2962, 0, 563, 679, 3159,
0, 0, 0, 770, 2479, 0, 460, 1500, 2451, 351, 0, 83, 0, 775, 672, 0,
1114, 429, 571, 0, 0, 0, 1136, 698, 0, 1131, 0, 0, 112, 0, 0, 0,
0, 0, 22, 0, 0, 482, 516, 0, 2624, 0, 444, 2529, 0, 2683, 958, 0,
1038, 0, 3099, 1311, 1111, 0, 983, 1281, 529, 1320, 0, 798, 1722, 0, 0, 2541,
718, 0, 965, 0, 1454, 0, 2828, 0, 3144, 0, 0, 2759, 0, 0, 0, 0,
0, 4, 0, 0, 125, 0, 0, 2418, 0, 870, 924, 1547, 0, 3193, 1083, 0,
1199, 0, 3205, 0, 350, 0, 0, 0, 54, 892, 0, 0, 0, 1869, 0, 1868,
2494, 831, 3183, 0, 1460, 0, 1654, 0, 0, 639, 0, 2164, 0, 0, 0, 0,
724, 0, 0, 0, 476, 0, 1306, 931, 0, 3133, 2671, 549, 731, 0, 0, 0,
0, 0, 0, 276, 0, 0, 0, 42, 0, 0, 2663, 1055, 0, 1355, 0, 0,
2316, 2662, 347, 928, 0, 407, 0, 0, 0, 1033, 0, 0, 0, 0, 0, 0,
674, 272, 0, 0, 593, 0, 729, 0, 0, 0, 0, 0, 2282, 0, 1260, 370,
0, 2158, 0, 0, 684, 0, 715, 0, 0, 0, 759, 1102, 0, 1579, 0, 1137,
0, 0, 0, 407, 0, 14, 981, 0, 0, 2715, 705, 0, 0, 78, 0, 0,
0, 29, 2460, 0, 0, 0, 0, 558, 2871, 0, 2411, 0, 0, 604, 2641, 0,
0, 0, 137, 0, 1223, 0, 561, 0, 0, 2788, 1225, 901, 0, 1681, 0, 0,
454, 596, 0, 0, 0, 0, 2327, 0, 0, 0, 0, 1667, 1352, 0, 0, 506,
0, 142, 0, 2654, 1603, 495, 1211, 443, 453, 1157, 584, 1576, 239, 1089, 373, 1536,
1959, 0, 58, 30, 0, 0, 0, 0, 0, 0, 0, 219, 0, 0, 0, 0,
355, 1381, 254, 1563, 0, 418, 68, 2743, 1193, 0, 0, 782, 0, 102, 0, 2896,
1325, 0, 662, 537, 3003, 3020, 933, 0, 0, 1759, 842, 0, 1676, 0, 0, 435,
0, 0, 0, 2888, 0, 474, 1325, 0, 0, 957, 0, 0, 585, 0, 0, 767,
298, 962, 671, 0, 2774, 299, 857, 0, 0, 1361, 0, 0, 426, 0, 2628, 0,
776, 2366, 1266, 654, 0, 2283, 140, 0, 605, 0, 0, 0, 11, 245, 1288, 0,
0, 827, 0, 3086, 1066, 48, 2279, 3000, 93, 3061, 2984, 0, 3004, 0, 0, 0,
1374, 0, 1969, 0, 0, 0, 0, 2037, 1024, 2882, 499, 0, 0, 2051, 427, 0,
82, 545, 1336, 0, 0, 0, 2521, 2316, 1155, 0, 0, 879, 0, 610, 0, 21,
2280, 2856, 936, 0, 1043, 0, 2195, 0, 0, 664, 0, 872, 269, 0, 0, 0,
144, 0, 0, 0, 133, 0, 0, 213, 1313, 103, 2534, 2122, 0, 1285, 21, 1213,
871, 0, 982, 0, 309, 1478, 1980, 2587, 0, 0, 1246, 391, 2040, 792, 0, 858,
302, 1299, 719, 0, 0, 726, 1142, 0, 36, 0, 21, 0, 1392, 0, 297, 0,
0, 346, 656, 1295, 604, 1394, 0, 0, 1638, 0, 2648, 0, 0, 1522, 887, 2036,
478, 2597, 657, 2538, 0, 598, 0, 0, 1596, 0, 1851, 0, 0, 826, 144, 894,
1544, 717, 161, 606, 0, 396, 2646, 1182, 0, 5, 963, 677, 0, 0, 457, 1185,
227, 2471, 1139, 0, 0, 0, 5, 5, 0, 40, 1048, 902, 2988, 820, 2093, 0,
1015, 0, 0, 737, 0, 1144, 0, 449, 0, 388, 805, 312, 2547, 1230, 0, 0,
2322, 2182, 269, 1447, 3134, 866, 0, 0, 1670, 1150, 0, 1419, 0, 2, 1491, 464,
0, 2657, 0, 0, 0, 1033, 2789, 973, 1400, 2805, 906, 3150, 0, 1165, 1168, 2966,
0, 1577, 0, 394, 1423, 0, 157, 2276, 0, 0, 1260, 211, 0, 0, 1240, 429,
0, 176, 1050, 449, 31, 0, 0, 1326, 0, 0, 1126, 0, 352, 1205, 0, 2465,
0, 1758, 0, 0, 18, 1449, 627, 262, 0, 2767, 0, 0, 0, 1294, 0, 0,
0, 0, 208, 1539, 0, 0, 0, 0, 938, 0, 0, 2614, 0, 475, 843, 0,
2668, 0, 1073, 0, 0, 186, 2444, 236, 8, 0, 110, 795, 0, 0, 0, 0,
0, 0, 0, 2755, 1492, 0, 559, 727, 813, 0, 0, 542, 659, 406, 1463, 514,
0, 0, 2976, 0, 1206, 740, 2036, 250, 961, 0, 999, 0, 1769, 0, 1330, 485,
1402, 0, 1098, 3054, 2104, 0, 494, 0, 0, 3115, 0, 71, 0, 0, 0, 0,
114, 345, 0, 0, 2819, 1036, 3108, 0, 407, 0, 638, 0, 0, 0, 1145, 562,
0, 757, 2411, 0, 1141, 87, 3083, 3070, 0, 0, 87, 0, 3046, 0, 1255, 0,
387, 0, 1151, 0, 0, 3038, 2228, 0, 0, 0, 540, 913, 1119, 0, 0, 0,
562, 0, 0, 1024, 0, 455, 324, 0, 1010, 1483, 0, 793, 1188, 941, 0, 0,
52, 94, 0, 0, 1409, 1261, 0, 2894, 709, 0, 873, 2970, 0, 3201, 2897, 0,
3136, 285, 0, 2037, 2041, 240, 1357, 1148, 0, 2428, 0, 856, 1582, 0, 229, 0,
1191, 1138, 0, 0, 818, 116, 355, 2621, 1176, 0, 1979, 1610, 594, 0, 0, 0,
3174, 2985, 0, 1085, 255, 38, 2159, 1289, 774, 355, 0, 1281, 0, 2960, 639, 1247,
0, 0, 3128, 2993, 1299, 386, 2256, 851, 3067, 0, 0, 887, 0, 0, 1334, 0,
591, 160, 0, 89, 0, 669, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2208, 0, 0, 2708, 0, 1022, 972, 0, 486, 0, 1438, 357, 1329, 975, 1271, 1129,
3146, 0, 968, 869, 2210, 128, 2678, 0, 937, 0, 1063, 0, 0, 1267, 42, 2469,
75, 0, 157, 0, 2659, 2776, 1855, 1146, 641, 0, 0, 330, 0, 0, 1294, 0,
0, 0, 1229, 0, 826, 0, 878, 1398, 258, 0, 1713, 12, 0, 0, 246, 55,
583, 1565, 1645, 0, 268, 0, 2754, 985, 0, 234, 1550, 1070, 2369, 1154, 0, 2750,
0, 3037, 1408, 631, 941, 215, 268, 770, 3167, 2058, 1391, 0, 3153, 0, 1115, 2816,
0, 0, 2933, 1875, 0, 1041, 330, 0, 1975, 364, 925, 12, 2946, 0, 1064, 2853,
2069, 223, 3109, 2964, 112, 0, 1199, 0, 3196, 329, 1141, 696, 0, 1566, 0, 0,
0, 0, 287, 0, 0, 658, 0, 0, 1575, 101, 0, 0, 0, 1399, 0, 0,
782, 3054, 0, 0, 0, 0, 73, 0, 4, 0, 2300, 0, 212, 1217, 0, 0,
0, 680, 509, 498, 701, 520, 0, 0, 2111, 2885, 0, 1471, 424, 824, 0, 0,
0, 0, 1325, 0, 0, 0, 1697, 2443, 1076, 1630, 8, 1963, 0, 0, 563, 3013,
0, 0, 3161, 2207, 0, 0, 729, 0, 845, 667, 0, 0, 522, 0, 766, 0,
991, 3074, 2716, 2969, 1375, 0, 0, 0, 0, 3006, 273, 0, 0, 904, 275, 0,
2320, 0, 0, 1365, 905, 720, 627, 0, 0, 1401, 1100, 0, 1509, 0, 38, 0,
3148, 0, 0, 0, 249, 0, 0, 0, 1085, 281, 2243, 0, 315, 0, 0, 1172,
0, 0, 0, 1088, 1517, 759, 2866, 0, 0, 0, 1293, 1974, 2572, 0, 1472, 0,
86, 1416, 0, 1727, 114, 623, 1339, 1011, 3, 3203, 888, 2269, 268, 0, 679, 0,
1231, 0, 1211, 921, 340, 1222, 0, 0, 0, 2686, 0, 1634, 0, 1594, 0, 664,
0, 3086, 0, 1142, 911, 0, 836, 1155, 2773, 1536, 1800, 1394, 495, 0, 0, 2977,
0, 0, 989, 296, 266, 0, 0, 522, 0, 1380, 994, 1327, 0, 1794, 987, 0,
2402, 84, 0, 0, 3038, 0, 1163, 2073, 425, 0, 0, 755, 0, 1570, 0, 895,
0, 2186, 0, 51, 392, 0, 0, 617, 0, 0, 256, 0, 0, 0, 0, 0,
0, 631, 3142, 521, 2385, 2707, 0, 614, 3133, 0, 2818, 0, 0, 2522, 0, 1029,
162, 0, 0, 1224, 1218, 0, 1445, 0, 1483, 992, 628, 1284, 0, 632, 183, 0,
0, 1845, 1232, 3168, 2066, 2553, 0, 0, 0, 2826, 1495, 2032, 0, 2884, 1153, 602,
0, 823, 1448, 1601, 2244, 33, 1979, 0, 93, 0, 0, 0, 2184, 2933, 0, 1416,
1356, 210, 0, 1300, 0, 0, 0, 0, 1762, 2710, 2262, 0, 1089, 0, 1305, 2904,
1257, 1744, 0, 703, 1094, 1398, 0, 2550, 1656, 3145, 0, 1392, 1802, 0, 0, 1081,
866, 932, 1249, 0, 162, 416, 83, 42, 0, 2704, 2689, 0, 0, 0, 1800, 0,
31, 97, 0, 65, 738, 434, 0, 0, 878, 0, 0, 0, 2466, 1019, 0, 0,
3047, 0, 0, 0, 1187, 792, 0, 734, 2781, 1182, 0, 397, 2959, 908, 0, 1296,
0, 0, 0, 2445, 1608, 190, 578, 0, 860, 0, 0, 258, 2765, 0, 0, 935,
0, 0, 0, 0, 769, 655, 0, 1746, 0, 0, 3094, 1571, 1164, 0, 0, 40,
1040, 437, 0, 93, 0, 1079, 2208, 0, 0, 1063, 3119, 0, 1109, 1135, 2512, 0,
0, 489, 0, 568, 3181, 2263, 1243, 3113, 0, 0, 397, 0, 0, 0, 0, 0,
267, 115, 2498, 1167, 583, 1654, 806, 0, 2534, 264, 0, 0, 0, 92, 218, 0,
0, 7, 0, 0, 180, 0, 1239, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1563, 1452, 2734, 790, 2687, 0, 1613, 2930, 0, 1770, 2508, 0, 840, 1695, 881, 2102,
2997, 0, 763, 1075, 802, 473, 934, 1757, 0, 0, 3095, 0, 0, 1654, 0, 576,
358, 2230, 0, 0, 1014, 0, 0, 193, 2930, 3126, 0, 1044, 2263, 1766, 87, 1069,
471, 547, 263, 830, 1314, 58, 163, 2821, 0, 198, 0, 2403, 1528, 2865, 0, 826,
0, 0, 206, 0, 2592, 1156, 0, 25, 1056, 3047, 2937, 0, 1452, 1814, 1519, 0,
0, 0, 2025, 1113, 305, 0, 46, 0, 2218, 1248, 3063, 0, 281, 954, 124, 0,
94, 383, 2078, 523, 2425, 43, 0, 552, 0, 0, 2589, 0, 0, 1162, 2884, 181,
1766, 0, 2608, 0, 0, 936, 445, 104, 0, 0, 814, 0, 0, 0, 0, 0,
647, 451, 1025, 1001, 1236, 2275, 1180, 0, 0, 0, 1578, 1183, 171, 0, 2602, 1436,
0, 0, 0, 300, 0, 0, 596, 0, 1252, 1318, 2538, 1070, 435, 832, 0, 1317,
257, 3014, 1181, 493, 39, 540, 768, 0, 1040, 308, 492, 0, 0, 0, 2442, 0,
0, 1464, 1394, 0, 0, 1007, 0, 2657, 0, 0, 709, 1311, 0, 1237, 0, 0,
0, 0, 0, 1552, 659, 959, 883, 0, 241, 1301, 2755, 0, 0, 3137, 0, 0,
0, 1476, 13, 395, 0, 1916, 0, 0, 518, 0, 545, 2529, 0, 0, 0, 2965,
1111, 385, 912, 2879, 0, 148, 1283, 325, 0, 2659, 781, 0, 235, 0, 341, 0,
2833, 0, 0, 2066, 1100, 608, 0, 2918, 2971, 3182, 0, 451, 1703, 1705, 815, 142,
2462, 282, 0, 0, 1621, 501, 0, 365, 327, 0, 373, 1344, 0, 762, 1473, 525,
3094, 0, 0, 0, 0, 1173, 0, 0, 789, 2341, 2974, 0, 0, 1236, 3106, 2543,
500, 2526, 1327, 973, 0, 694, 0, 2400, 2442, 1090, 130, 0, 2047, 0, 511, 0,
620, 412, 0, 409, 942, 1193, 0, 3108, 1436, 508, 0, 1041, 1244, 722, 0, 1206,
155, 2007, 374, 401, 13, 146, 622, 1276, 1018, 0, 0, 0, 1418, 1541, 0, 0,
230, 0, 715, 358, 2305, 1057, 286, 0, 2675, 0, 2837, 1282, 0, 587, 0, 841,
3139, 0, 1643, 0, 912, 0, 580, 1503, 0, 0, 69, 2560, 0, 0, 543, 90,
80, 0, 0, 471, 313, 0, 0, 0, 0, 0, 0, 2621, 1547, 2913, 0, 63,
1078, 384, 2778, 1182, 2878, 11, 0, 1108, 1542, 0, 0, 914, 1443, 0, 2337, 1529,
0, 626, 0, 972, 0, 813, 0, 225, 1047, 1322, 1155, 1864, 510, 308, 0, 0,
456, 0, 422, 2906, 758, 0, 2102, 425, 1426, 686, 0, 748, 752, 1614, 406, 86,
519, 299, 0, 0, 161, 1362, 643, 0};
0, 0, 0, 0, 0, 0, 0, 863, 973, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1650, 2907, 0, 409, 954, 0, 0, 1096, 0, 966, 506, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1368, 0, 0, 0, 0, 0, 0, 0,
0, 2626, 0, 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, 2780, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2149, 0, 677, 0, 0, 0,
0, 0, 0, 0, 2606, 0, 1146, 1990, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 49, 1152, 0, 0, 0, 0, 2723, 959, 1393, 365, 0,
0, 0, 1485, 0, 0, 2836, 0, 0, 0, 123, 0, 2635, 0, 0, 0, 1238,
489, 248, 0, 1358, 762, 0, 0, 0, 0, 2607, 0, 321, 0, 0, 0, 0,
0, 0, 139, 0, 0, 0, 2604, 398, 0, 0, 0, 0, 0, 0, 0, 0,
1953, 0, 2094, 0, 0, 0, 0, 0, 202, 0, 0, 0, 47, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2963, 1015, 2305, 493,
0, 189, 549, 0, 0, 0, 0, 0, 98, 0, 0, 1862, 0, 26, 0, 0,
1156, 0, 0, 2870, 0, 2297, 0, 0, 0, 3125, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1004, 0, 1452, 0, 0, 2817, 0, 3102, 821, 590, 0, 1946, 0,
0, 0, 370, 2516, 1986, 1325, 0, 1995, 1125, 0, 0, 1795, 0, 773, 649, 0,
2705, 1618, 0, 1910, 2044, 0, 0, 0, 976, 3135, 0, 2034, 2489, 0, 0, 1964,
140, 0, 0, 0, 0, 0, 897, 0, 745, 0, 2747, 0, 0, 229, 1597, 0,
1305, 0, 2020, 0, 0, 0, 745, 0, 0, 497, 0, 0, 0, 0, 1542, 613,
0, 933, 0, 518, 0, 0, 0, 174, 2732, 0, 0, 1887, 0, 991, 0, 0,
0, 237, 0, 390, 725, 1583, 0, 3057, 0, 2412, 0, 0, 0, 0, 0, 0,
1313, 2567, 0, 2871, 512, 940, 361, 3122, 2726, 0, 3184, 0, 0, 377, 223, 0,
1239, 0, 598, 0, 0, 0, 0, 1225, 1219, 0, 0, 0, 1682, 0, 0, 0,
700, 0, 0, 1312, 0, 2702, 0, 0, 1222, 1066, 0, 1611, 0, 0, 0, 0,
1279, 0, 0, 0, 0, 887, 0, 1619, 0, 691, 2993, 0, 0, 0, 0, 234,
0, 1099, 958, 0, 277, 1626, 0, 2136, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 675, 1934, 1604, 0, 0, 0, 0, 0, 0, 919, 536, 0, 0, 0,
607, 2954, 0, 0, 1606, 0, 0, 0, 0, 0, 0, 0, 291, 431, 1696, 0,
0, 0, 0, 1111, 0, 642, 1124, 3026, 0, 1383, 1187, 0, 0, 0, 763, 0,
0, 144, 0, 0, 3011, 0, 0, 0, 2986, 2173, 1139, 1470, 2294, 0, 411, 0,
0, 0, 1014, 0, 426, 0, 0, 0, 0, 141, 684, 0, 1754, 765, 1585, 0,
0, 0, 0, 0, 3201, 540, 480, 0, 0, 749, 592, 0, 0, 0, 0, 1394,
0, 375, 0, 0, 0, 2633, 0, 1921, 0, 0, 0, 0, 0, 2834, 676, 0,
0, 0, 2625, 0, 2504, 0, 783, 0, 0, 1076, 0, 0, 0, 0, 0, 0,
0, 2991, 328, 0, 0, 2723, 323, 0, 0, 0, 0, 0, 0, 0, 2954, 0,
879, 0, 0, 0, 0, 0, 1497, 0, 0, 2179, 1283, 0, 2326, 0, 0, 2434,
0, 225, 0, 125, 0, 0, 0, 1741, 0, 0, 2977, 165, 280, 852, 0, 88,
0, 2603, 0, 1069, 0, 0, 2855, 0, 0, 0, 935, 281, 468, 650, 0, 0,
0, 797, 0, 0, 0, 0, 0, 829, 0, 888, 284, 0, 0, 2646, 3011, 0,
0, 2534, 2640, 2144, 110, 1468, 1352, 2420, 0, 2453, 0, 0, 0, 0, 0, 991,
2645, 0, 1618, 0, 0, 0, 0, 2139, 64, 0, 649, 1090, 0, 0, 1222, 3137,
757, 0, 0, 2571, 0, 0, 2827, 2966, 0, 0, 228, 1307, 1955, 2122, 2263, 806,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 0, 3038, 3182, 378, 698,
0, 1193, 3155, 826, 0, 0, 0, 0, 0, 969, 0, 245, 577, 2888, 0, 0,
792, 1785, 103, 639, 0, 0, 1484, 0, 0, 430, 0, 0, 0, 0, 0, 3195,
2927, 0, 0, 0, 157, 2109, 0, 0, 1775, 1625, 0, 0, 0, 0, 0, 0,
2785, 1022, 1405, 2270, 869, 0, 0, 0, 0, 614, 0, 0, 258, 0, 265, 182,
834, 2249, 54, 0, 1126, 0, 0, 445, 0, 3196, 1848, 0, 0, 0, 744, 0,
0, 0, 0, 0, 695, 1105, 3087, 0, 0, 1018, 1098, 0, 151, 1360, 1363, 0,
0, 0, 0, 0, 3085, 2669, 2820, 0, 0, 0, 0, 636, 0, 2467, 0, 2565,
0, 0, 2054, 1296, 0, 1540, 0, 0, 1511, 2323, 0, 0, 23, 0, 0, 0,
145, 0, 2458, 0, 2017, 513, 356, 827, 0, 0, 0, 0, 0, 1263, 141, 2470,
0, 0, 0, 0, 1556, 184, 0, 0, 0, 0, 0, 1812, 134, 0, 1828, 0,
0, 962, 998, 0, 792, 2681, 525, 0, 0, 2441, 0, 0, 0, 0, 678, 0,
0, 296, 1343, 0, 1032, 0, 0, 2047, 0, 0, 0, 0, 838, 321, 0, 2001,
1096, 1123, 1411, 0, 0, 0, 0, 2373, 595, 213, 643, 851, 2228, 149, 678, 0,
0, 0, 2902, 0, 1065, 1175, 894, 0, 457, 1283, 846, 0, 1083, 216, 399, 0,
0, 134, 0, 324, 2527, 345, 2160, 0, 0, 1671, 2991, 6, 1407, 0, 0, 0,
0, 0, 126, 400, 85, 0, 3199, 0, 447, 0, 0, 0, 671, 1491, 0, 2038,
0, 2963, 1988, 3141, 2720, 1053, 0, 0, 2745, 0, 348, 0, 1073, 0, 528, 1842,
0, 0, 879, 1931, 2837, 667, 0, 0, 288, 0, 0, 217, 0, 0, 638, 731,
960, 0, 0, 0, 41, 334, 1890, 2773, 0, 0, 0, 0, 1454, 3018, 0, 1803,
0, 0, 448, 0, 248, 3011, 421, 0, 0, 2750, 0, 2236, 0, 0, 1000, 0,
0, 0, 0, 221, 2199, 0, 0, 527, 0, 0, 2804, 0, 0, 0, 0, 1631,
0, 0, 2912, 279, 0, 2189, 1139, 3149, 0, 2968, 0, 1688, 2065, 1068, 1160, 0,
0, 0, 757, 0, 629, 364, 0, 0, 0, 283, 783, 0, 1763, 0, 0, 1686,
0, 192, 828, 0, 0, 455, 522, 0, 0, 0, 0, 3002, 1948, 0, 0, 200,
0, 0, 846, 183, 2666, 0, 296, 0, 2882, 3082, 2217, 0, 944, 0, 0, 0,
3070, 2660, 0, 0, 469, 254, 0, 0, 1341, 337, 0, 594, 602, 0, 998, 0,
0, 0, 0, 0, 0, 0, 548, 2769, 0, 0, 0, 2405, 2387, 0, 215, 0,
0, 0, 0, 0, 0, 0, 0, 614, 0, 0, 186, 210, 1352, 3104, 0, 54,
402, 1154, 708, 0, 107, 0, 0, 0, 408, 2385, 0, 117, 2046, 2888, 2432, 2449,
0, 731, 2650, 0, 0, 0, 2638, 0, 827, 510, 803, 0, 0, 0, 62, 0,
0, 1875, 1895, 768, 50, 0, 0, 0, 0, 36, 0, 0, 0, 174, 2062, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 462, 0, 0, 0, 0, 1556,
0, 0, 1071, 832, 0, 1356, 0, 0, 0, 0, 0, 0, 160, 537, 0, 0,
0, 0, 0, 304, 77, 0, 1538, 0, 0, 0, 2465, 0, 0, 0, 0, 2796,
0, 0, 0, 0, 2434, 0, 0, 1486, 0, 0, 0, 2513, 0, 0, 0, 1048,
631, 0, 0, 0, 1039, 278, 0, 0, 0, 1505, 690, 2960, 0, 565, 677, 3114,
0, 0, 0, 772, 2479, 0, 460, 1502, 2451, 351, 0, 83, 0, 779, 674, 0,
1116, 419, 573, 0, 0, 0, 1138, 708, 0, 1133, 0, 0, 112, 0, 0, 0,
0, 0, 22, 0, 0, 482, 526, 0, 2622, 0, 444, 2523, 0, 2681, 960, 0,
1044, 0, 3099, 1313, 1113, 0, 981, 1326, 529, 1322, 0, 798, 1724, 0, 0, 2541,
722, 0, 967, 0, 1456, 0, 2826, 0, 3136, 0, 0, 2763, 0, 0, 0, 0,
0, 4, 0, 0, 123, 0, 0, 2416, 0, 872, 926, 1547, 0, 3193, 1083, 0,
1201, 0, 3205, 0, 350, 0, 0, 0, 54, 890, 0, 0, 0, 1877, 0, 1874,
2494, 823, 3183, 0, 1460, 0, 1664, 0, 0, 641, 0, 2166, 0, 0, 0, 0,
724, 0, 0, 0, 476, 0, 1308, 933, 0, 3133, 2679, 553, 733, 0, 0, 0,
0, 0, 0, 276, 0, 0, 0, 36, 0, 0, 2657, 1057, 0, 1351, 0, 0,
2324, 2660, 347, 930, 0, 409, 0, 0, 0, 1035, 0, 0, 0, 0, 0, 0,
676, 270, 0, 0, 595, 0, 733, 0, 0, 0, 0, 0, 2280, 0, 1262, 366,
0, 2166, 0, 0, 686, 0, 719, 0, 0, 0, 761, 1104, 0, 1579, 0, 1139,
0, 0, 0, 407, 0, 18, 981, 0, 0, 2713, 711, 0, 0, 78, 0, 0,
0, 27, 2468, 0, 0, 0, 0, 556, 2826, 0, 2411, 0, 0, 602, 2633, 0,
0, 0, 137, 0, 1225, 0, 563, 0, 0, 2790, 1225, 903, 0, 1673, 0, 0,
454, 600, 0, 0, 0, 0, 2327, 0, 0, 0, 0, 1665, 1354, 0, 0, 514,
0, 142, 0, 2654, 1607, 495, 1213, 404, 453, 1155, 586, 1584, 239, 1087, 373, 1536,
1959, 0, 52, 30, 0, 0, 0, 0, 0, 0, 0, 219, 0, 0, 0, 0,
353, 1383, 256, 1563, 0, 414, 68, 2743, 1195, 0, 0, 782, 0, 102, 0, 2898,
1333, 0, 664, 539, 3009, 3020, 935, 0, 0, 1755, 840, 0, 1680, 0, 0, 439,
0, 0, 0, 2884, 0, 476, 1327, 0, 0, 959, 0, 0, 583, 0, 0, 769,
300, 964, 675, 0, 2731, 299, 853, 0, 0, 1363, 0, 0, 426, 0, 2628, 0,
778, 2366, 1268, 656, 0, 2281, 140, 0, 603, 0, 0, 0, 11, 245, 1296, 0,
0, 827, 0, 3084, 1068, 48, 2277, 3002, 93, 3067, 2984, 0, 3010, 0, 0, 0,
1376, 0, 1973, 0, 0, 0, 0, 2037, 1024, 2880, 497, 0, 0, 2043, 425, 0,
82, 547, 1338, 0, 0, 0, 2523, 2314, 1157, 0, 0, 885, 0, 612, 0, 21,
2280, 2852, 932, 0, 1045, 0, 2191, 0, 0, 670, 0, 874, 269, 0, 0, 0,
142, 0, 0, 0, 133, 0, 0, 213, 1315, 101, 2532, 2128, 0, 1287, 25, 1215,
873, 0, 984, 0, 303, 1480, 1978, 2575, 0, 0, 1248, 387, 2034, 792, 0, 860,
298, 1301, 717, 0, 0, 728, 1144, 0, 36, 0, 21, 0, 1398, 0, 297, 0,
0, 352, 658, 1297, 604, 1394, 0, 0, 1642, 0, 2650, 0, 0, 1528, 891, 2036,
476, 2601, 659, 2548, 0, 600, 0, 0, 1596, 0, 1851, 0, 0, 826, 138, 896,
1544, 709, 163, 608, 0, 396, 2636, 1180, 0, 3, 965, 679, 0, 0, 457, 1187,
227, 2475, 1137, 0, 0, 0, 5, 5, 0, 40, 1050, 945, 2992, 824, 2093, 0,
1013, 0, 0, 739, 0, 1146, 0, 449, 0, 388, 801, 312, 2539, 1232, 0, 0,
2326, 2180, 263, 1449, 3136, 868, 0, 0, 1670, 1152, 0, 1415, 0, 2, 1495, 462,
0, 2665, 0, 0, 0, 1035, 2789, 975, 1408, 2807, 908, 3150, 0, 1167, 1166, 2964,
0, 1579, 0, 394, 1423, 0, 151, 2272, 0, 0, 1262, 211, 0, 0, 1242, 429,
0, 178, 1048, 449, 33, 0, 0, 1328, 0, 0, 1128, 0, 352, 1205, 0, 2463,
0, 1803, 0, 0, 18, 1449, 623, 262, 0, 2767, 0, 0, 0, 1294, 0, 0,
0, 0, 208, 1539, 0, 0, 0, 0, 940, 0, 0, 2614, 0, 483, 845, 0,
2670, 0, 1075, 0, 0, 186, 2442, 236, 8, 0, 110, 799, 0, 0, 0, 0,
0, 0, 0, 2747, 1494, 0, 561, 727, 811, 0, 0, 542, 661, 406, 1463, 512,
0, 0, 2974, 0, 1208, 742, 2044, 250, 963, 0, 993, 0, 1763, 0, 1332, 485,
1404, 0, 1100, 3062, 2102, 0, 491, 0, 0, 3115, 0, 71, 0, 0, 0, 0,
114, 345, 0, 0, 2813, 1038, 3108, 0, 407, 0, 681, 0, 0, 0, 1147, 564,
0, 759, 2411, 0, 1145, 87, 3081, 3062, 0, 0, 93, 0, 3044, 0, 1245, 0,
385, 0, 1153, 0, 0, 3038, 2228, 0, 0, 0, 538, 915, 1121, 0, 0, 0,
564, 0, 0, 1026, 0, 455, 328, 0, 1010, 1485, 0, 789, 1190, 945, 0, 0,
52, 96, 0, 0, 1411, 1263, 0, 2894, 711, 0, 875, 2968, 0, 3201, 2891, 0,
3134, 285, 0, 2039, 2039, 242, 1359, 1150, 0, 2434, 0, 858, 1584, 0, 221, 0,
1193, 1140, 0, 0, 820, 116, 355, 2621, 1178, 0, 1985, 1610, 596, 0, 0, 0,
3168, 2983, 0, 1087, 255, 38, 2161, 1291, 774, 351, 0, 1279, 0, 2966, 641, 1249,
0, 0, 3130, 3001, 1297, 386, 2250, 853, 3067, 0, 0, 889, 0, 0, 1336, 0,
593, 164, 0, 89, 0, 671, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2206, 0, 0, 2710, 0, 1024, 974, 0, 486, 0, 1440, 361, 1331, 977, 1267, 1131,
3146, 0, 968, 871, 2210, 134, 2678, 0, 941, 0, 1059, 0, 0, 1277, 40, 2461,
75, 0, 157, 0, 2657, 2774, 1900, 1148, 639, 0, 0, 328, 0, 0, 1296, 0,
0, 0, 1237, 0, 826, 0, 1848, 1400, 256, 0, 1719, 8, 0, 0, 246, 55,
585, 1565, 1657, 0, 262, 0, 2750, 991, 0, 236, 1552, 1062, 2367, 1156, 0, 2750,
0, 3039, 1410, 633, 943, 213, 268, 772, 3165, 2058, 1393, 0, 3155, 0, 1113, 2816,
0, 0, 2935, 1875, 0, 1043, 336, 0, 1983, 366, 972, 12, 2946, 0, 1066, 2849,
2079, 223, 3109, 2966, 110, 0, 1201, 0, 3196, 329, 1143, 698, 0, 1566, 0, 0,
0, 0, 287, 0, 0, 660, 0, 0, 1575, 99, 0, 0, 0, 1397, 0, 0,
780, 3054, 0, 0, 0, 0, 73, 0, 4, 0, 2300, 0, 212, 1217, 0, 0,
0, 682, 507, 496, 703, 518, 0, 0, 2105, 2883, 0, 1473, 424, 824, 0, 0,
0, 0, 1327, 0, 0, 0, 1695, 2443, 1078, 1630, 8, 1957, 0, 0, 557, 3009,
0, 0, 3163, 2203, 0, 0, 731, 0, 847, 675, 0, 0, 524, 0, 770, 0,
993, 3076, 2710, 2973, 1377, 0, 0, 0, 0, 3012, 273, 0, 0, 906, 275, 0,
2316, 0, 0, 1367, 907, 724, 629, 0, 0, 1407, 1096, 0, 1509, 0, 38, 0,
3150, 0, 0, 0, 249, 0, 0, 0, 1087, 283, 2243, 0, 311, 0, 0, 1174,
0, 0, 0, 1090, 1517, 767, 2864, 0, 0, 0, 1295, 1976, 2576, 0, 1484, 0,
80, 1416, 0, 1727, 108, 627, 1339, 1013, 3, 3203, 890, 2267, 276, 0, 681, 0,
1233, 0, 1213, 923, 340, 1224, 0, 0, 0, 2686, 0, 1632, 0, 1594, 0, 666,
0, 3086, 0, 1144, 913, 0, 838, 1163, 2763, 1532, 1800, 1396, 503, 0, 0, 2977,
0, 0, 991, 296, 268, 0, 0, 520, 0, 1386, 996, 1288, 0, 1788, 989, 0,
2402, 84, 0, 0, 3038, 0, 1165, 2071, 425, 0, 0, 759, 0, 1570, 0, 897,
0, 2176, 0, 45, 402, 0, 0, 619, 0, 0, 256, 0, 0, 0, 0, 0,
0, 635, 3142, 519, 2377, 2715, 0, 616, 3088, 0, 2816, 0, 0, 2522, 0, 1031,
160, 0, 0, 1226, 1220, 0, 1447, 0, 1487, 994, 628, 1286, 0, 634, 189, 0,
0, 1847, 1234, 3164, 2060, 2555, 0, 0, 0, 2826, 1501, 2030, 0, 2886, 1155, 604,
0, 823, 1450, 1601, 2244, 33, 1983, 0, 93, 0, 0, 0, 2182, 2943, 0, 1418,
1358, 210, 0, 1302, 0, 0, 0, 0, 1776, 2708, 2258, 0, 1091, 0, 1307, 2900,
1259, 1744, 0, 705, 1096, 1400, 0, 2552, 1650, 3137, 0, 1394, 1802, 0, 0, 1077,
866, 934, 1251, 0, 164, 416, 83, 42, 0, 2707, 2685, 0, 0, 0, 1800, 0,
31, 97, 0, 65, 740, 434, 0, 0, 880, 0, 0, 0, 2466, 1021, 0, 0,
3047, 0, 0, 0, 1191, 788, 0, 732, 2773, 1188, 0, 397, 2959, 908, 0, 1296,
0, 0, 0, 2402, 1608, 196, 580, 0, 860, 0, 0, 258, 2767, 0, 0, 937,
0, 0, 0, 0, 771, 657, 0, 1742, 0, 0, 3094, 1571, 1164, 0, 0, 40,
1042, 431, 0, 89, 0, 1081, 2206, 0, 0, 1065, 3123, 0, 1111, 1137, 2510, 0,
0, 489, 0, 572, 3181, 2255, 1245, 3115, 0, 0, 405, 0, 0, 0, 0, 0,
261, 119, 2496, 1175, 585, 1652, 806, 0, 2536, 264, 0, 0, 0, 92, 218, 0,
0, 7, 0, 0, 180, 0, 1241, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1563, 1458, 2734, 790, 2683, 0, 1613, 2930, 0, 1770, 2518, 0, 842, 1689, 883, 2100,
3001, 0, 773, 1077, 802, 473, 936, 1763, 0, 0, 3095, 0, 0, 1660, 0, 578,
358, 2230, 0, 0, 1016, 0, 0, 185, 2930, 3126, 0, 1046, 2261, 1772, 87, 1071,
471, 547, 263, 830, 1386, 58, 163, 2819, 0, 198, 0, 2411, 1530, 2861, 0, 825,
0, 0, 206, 0, 2594, 1160, 0, 25, 1056, 3047, 2945, 0, 1454, 1816, 1521, 0,
0, 0, 2023, 1113, 305, 0, 46, 0, 2222, 1205, 3069, 0, 279, 956, 124, 0,
94, 383, 2080, 521, 2421, 43, 0, 552, 0, 0, 2591, 0, 0, 1166, 2886, 181,
1772, 0, 2602, 0, 0, 940, 445, 104, 0, 0, 826, 0, 0, 0, 0, 0,
645, 451, 1023, 1003, 1240, 2273, 1182, 0, 0, 0, 1582, 1185, 171, 0, 2598, 1434,
0, 0, 0, 300, 0, 0, 598, 0, 1254, 1320, 2536, 1072, 439, 832, 0, 1319,
257, 3018, 1191, 490, 39, 542, 770, 0, 1044, 312, 556, 0, 0, 0, 2446, 0,
0, 1466, 1394, 0, 0, 1007, 0, 2657, 0, 0, 705, 1311, 0, 1241, 0, 0,
0, 0, 0, 1552, 661, 961, 885, 0, 196, 1295, 2759, 0, 0, 3137, 0, 0,
0, 1474, 13, 395, 0, 1914, 0, 0, 522, 0, 547, 2527, 0, 0, 0, 2967,
1113, 385, 912, 2877, 0, 148, 1285, 325, 0, 2669, 781, 0, 235, 0, 341, 0,
2874, 0, 0, 2064, 1102, 614, 0, 2959, 2971, 3182, 0, 449, 1707, 1709, 815, 142,
2462, 282, 0, 0, 1621, 499, 0, 359, 327, 0, 373, 1346, 0, 764, 1475, 523,
3094, 0, 0, 0, 0, 1175, 0, 0, 789, 2341, 2968, 0, 0, 1238, 3106, 2553,
498, 2534, 1329, 975, 0, 688, 0, 2392, 2442, 1092, 128, 0, 2045, 0, 511, 0,
624, 412, 0, 409, 944, 1195, 0, 3108, 1438, 512, 0, 1041, 1246, 724, 0, 1208,
157, 2011, 374, 405, 11, 146, 616, 1278, 1020, 0, 0, 0, 1420, 1541, 0, 0,
230, 0, 717, 358, 2305, 1059, 284, 0, 2675, 0, 2845, 1284, 0, 589, 0, 845,
3141, 0, 1688, 0, 869, 0, 582, 1505, 0, 0, 69, 2558, 0, 0, 543, 90,
80, 0, 0, 473, 313, 0, 0, 0, 0, 0, 0, 2623, 1549, 2870, 0, 63,
1080, 384, 2772, 1184, 2876, 11, 0, 1110, 1542, 0, 0, 916, 1445, 0, 2345, 1529,
0, 632, 0, 974, 0, 813, 0, 225, 1049, 1324, 1159, 1868, 510, 310, 0, 0,
456, 0, 422, 2906, 760, 0, 2100, 427, 1428, 684, 0, 750, 754, 1614, 406, 86,
517, 299, 0, 0, 161, 1364, 645, 0};
int MangledHashG(const char *key, const int *T)
{
......@@ -260,22 +260,22 @@ constexpr int unmangledkT1[] = {246, 133, 248, 237, 59, 207, 93, 240, 98, 265,
constexpr int unmangledkT2[] = {166, 291, 199, 102, 183, 190, 20, 31, 50, 30, 134, 213, 202,
55, 268, 11, 15, 108, 22, 43, 119, 187, 239, 91, 190, 47};
constexpr int unmangledkG[] = {
0, 46, 0, 0, 0, 124, 0, 0, 0, 291, 0, 204, 0, 0, 230, 0, 0, 0, 0,
48, 0, 0, 0, 0, 0, 152, 153, 0, 60, 0, 227, 127, 0, 0, 161, 0, 0, 53,
0, 265, 0, 241, 0, 160, 155, 0, 0, 46, 22, 0, 106, 0, 147, 21, 0, 29, 0,
0, 0, 0, 84, 23, 16, 142, 177, 0, 18, 0, 23, 60, 255, 142, 135, 59, 225, 53,
35, 0, 0, 129, 142, 122, 0, 32, 0, 0, 75, 0, 0, 136, 291, 68, 0, 0, 0,
19, 64, 208, 0, 238, 280, 176, 116, 80, 81, 108, 0, 201, 45, 0, 0, 57, 268, 3,
277, 0, 39, 0, 31, 14, 0, 57, 181, 93, 277, 146, 0, 146, 153, 0, 0, 0, 158,
282, 0, 0, 65, 238, 158, 0, 73, 276, 0, 0, 185, 136, 0, 0, 0, 179, 0, 38,
0, 39, 0, 166, 88, 57, 0, 232, 0, 0, 57, 0, 80, 0, 0, 30, 0, 88, 0,
0, 75, 0, 105, 0, 9, 182, 0, 55, 0, 192, 21, 0, 0, 153, 76, 269, 0, 0,
125, 86, 0, 193, 279, 0, 0, 0, 128, 2, 0, 99, 0, 13, 64, 0, 28, 58, 67,
0, 117, 159, 0, 0, 5, 29, 0, 56, 186, 54, 0, 254, 180, 84, 287, 0, 117, 0,
204, 39, 5, 0, 0, 44, 151, 0, 0, 254, 0, 96, 136, 194, 152, 0, 166, 112, 87,
0, 0, 0, 0, 137, 0, 62, 15, 0, 0, 41, 274, 90, 236, 110, 0, 0, 118, 246,
273, 227, 0, 133, 0, 266, 0, 3, 0, 0, 95, 277, 89, 151, 156, 218, 282, 0, 0,
0, 0, 29, 54, 0, 126, 57};
0, 45, 0, 0, 0, 118, 0, 0, 0, 288, 0, 202, 0, 0, 235, 0, 0, 0, 0,
50, 0, 0, 0, 0, 0, 153, 155, 0, 64, 0, 225, 128, 0, 0, 162, 0, 0, 53,
0, 262, 0, 240, 0, 156, 156, 0, 0, 47, 20, 0, 105, 0, 148, 21, 0, 30, 0,
0, 0, 0, 84, 23, 16, 143, 176, 0, 18, 0, 24, 57, 255, 143, 136, 59, 231, 54,
36, 0, 0, 130, 141, 123, 0, 32, 0, 0, 76, 0, 0, 132, 291, 69, 0, 0, 0,
19, 64, 209, 0, 239, 283, 180, 117, 80, 81, 41, 0, 200, 44, 0, 0, 55, 283, 3,
274, 0, 39, 0, 49, 14, 0, 54, 185, 109, 276, 145, 0, 147, 149, 0, 0, 0, 154,
281, 0, 0, 65, 238, 159, 0, 73, 276, 0, 0, 184, 132, 0, 0, 0, 180, 0, 38,
0, 39, 0, 167, 88, 59, 0, 231, 0, 0, 58, 0, 81, 0, 0, 30, 0, 87, 0,
0, 75, 0, 104, 0, 9, 181, 0, 55, 0, 194, 22, 0, 0, 154, 76, 274, 0, 0,
124, 86, 0, 189, 277, 0, 0, 0, 129, 1, 0, 98, 0, 10, 49, 0, 30, 56, 67,
0, 118, 160, 0, 0, 5, 29, 0, 56, 185, 54, 0, 253, 184, 84, 283, 0, 119, 0,
203, 39, 5, 0, 0, 44, 155, 0, 0, 256, 0, 93, 137, 196, 153, 0, 167, 113, 87,
0, 0, 0, 0, 143, 0, 62, 15, 0, 0, 41, 274, 90, 239, 111, 0, 0, 119, 246,
273, 221, 0, 134, 0, 269, 0, 277, 0, 0, 97, 282, 86, 152, 157, 217, 279, 0, 0,
0, 0, 32, 58, 0, 125, 54};
int UnmangledHashG(const char *key, const int *T)
{
......
......@@ -33,251 +33,251 @@ constexpr int mangledkT2[] = {1129, 226, 3871, 1567, 3267, 3307, 452, 3099, 23
3764, 2526, 2149, 2101, 1636, 2341, 2985, 454, 627, 1307,
466, 537, 2536, 736, 2238, 1704, 1050, 3135, 564, 182};
constexpr int mangledkG[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 365, 0, 0, 2752, 0, 0, 402,
3397, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2474,
0, 650, 0, 0, 0, 0, 0, 642, 0, 0, 0, 0, 0, 232, 0, 0,
0, 2514, 1777, 3340, 0, 0, 362, 0, 109, 0, 0, 0, 0, 3022, 2888, 0,
0, 0, 0, 0, 0, 988, 0, 2459, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1189, 0, 0, 0, 0, 0, 2292, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 2264, 0, 0, 0, 0, 0, 0, 3238, 0, 0, 1782, 1889,
2988, 2352, 395, 0, 0, 0, 0, 0, 2268, 475, 603, 0, 0, 2986, 0, 0,
0, 0, 0, 0, 0, 191, 1035, 0, 0, 0, 0, 0, 0, 0, 0, 1135,
0, 0, 1451, 0, 0, 0, 0, 3309, 0, 0, 1839, 0, 0, 0, 3268, 0,
0, 1319, 0, 0, 0, 0, 0, 744, 0, 0, 0, 193, 45, 0, 3153, 0,
0, 0, 11, 2346, 0, 1453, 2954, 192, 0, 2649, 0, 0, 3238, 3552, 3391, 0,
2499, 3252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1951, 0, 0, 1005,
2021, 2827, 0, 0, 0, 0, 2882, 2428, 3786, 0, 0, 0, 3852, 0, 0, 250,
0, 0, 0, 0, 2672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1239, 0,
0, 0, 0, 0, 264, 1192, 0, 0, 188, 0, 1139, 0, 840, 841, 0, 0,
1814, 3065, 0, 3626, 2059, 0, 84, 0, 860, 0, 0, 0, 1962, 826, 0, 2022,
0, 0, 0, 0, 3393, 1329, 0, 0, 0, 109, 0, 0, 0, 0, 3817, 0,
3075, 0, 0, 0, 617, 0, 0, 2650, 0, 0, 436, 3506, 122, 88, 3253, 761,
1027, 0, 0, 1637, 0, 230, 1480, 0, 0, 0, 0, 0, 0, 2953, 0, 0,
0, 3203, 0, 95, 0, 3283, 0, 0, 0, 233, 0, 0, 1953, 0, 0, 0,
0, 3907, 3490, 0, 1577, 705, 0, 0, 2687, 0, 2466, 3277, 0, 0, 1527, 663,
0, 0, 1570, 0, 620, 3195, 0, 0, 1463, 426, 0, 0, 0, 0, 2128, 1937,
135, 0, 551, 0, 1645, 0, 939, 3411, 1700, 1982, 0, 3505, 0, 654, 0, 0,
0, 0, 0, 1720, 741, 3341, 0, 2086, 164, 0, 2179, 1868, 0, 0, 0, 0,
0, 3779, 1136, 0, 1236, 0, 403, 0, 919, 345, 0, 1835, 3431, 2900, 0, 0,
0, 0, 2440, 2580, 0, 0, 0, 0, 0, 3727, 0, 3231, 13, 0, 2918, 422,
0, 0, 0, 0, 0, 3898, 0, 0, 0, 0, 0, 0, 0, 1803, 0, 3313,
0, 3365, 0, 0, 0, 2637, 0, 0, 0, 0, 0, 2487, 86, 1418, 0, 1118,
109, 0, 0, 0, 0, 3110, 3611, 2071, 0, 3675, 669, 1955, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 2263, 2684, 0, 0, 821, 2906, 0, 0, 1530, 1292,
0, 0, 0, 0, 0, 0, 0, 0, 0, 375, 0, 0, 2756, 0, 0, 392,
3385, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2472,
0, 650, 0, 0, 0, 0, 0, 642, 0, 0, 0, 0, 0, 228, 0, 0,
0, 2514, 1769, 3341, 0, 0, 362, 0, 113, 0, 0, 0, 0, 3022, 2884, 0,
0, 0, 0, 0, 0, 996, 0, 2455, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1187, 0, 0, 0, 0, 0, 2290, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 2262, 0, 0, 0, 0, 0, 0, 3234, 0, 0, 1779, 1891,
2980, 2354, 399, 0, 0, 0, 0, 0, 2266, 473, 615, 0, 0, 2990, 0, 0,
0, 0, 0, 0, 0, 191, 1031, 0, 0, 0, 0, 0, 0, 0, 0, 1131,
0, 0, 1456, 0, 0, 0, 0, 3312, 0, 0, 1845, 0, 0, 0, 3272, 0,
0, 1316, 0, 0, 0, 0, 0, 746, 0, 0, 0, 193, 41, 0, 3149, 0,
0, 0, 11, 2352, 0, 1453, 2954, 186, 0, 2647, 0, 0, 3238, 3552, 3397, 0,
2497, 3256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1947, 0, 0, 995,
2013, 2827, 0, 0, 0, 0, 2876, 2426, 3786, 0, 0, 0, 3852, 0, 0, 254,
0, 0, 0, 0, 2672, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1241, 0,
0, 0, 0, 0, 264, 1189, 0, 0, 192, 0, 1133, 0, 838, 843, 0, 0,
1816, 3067, 0, 3627, 2059, 0, 92, 0, 856, 0, 0, 0, 1962, 824, 0, 2026,
0, 0, 0, 0, 3395, 1327, 0, 0, 0, 109, 0, 0, 0, 0, 3814, 0,
3079, 0, 0, 0, 617, 0, 0, 2648, 0, 0, 442, 3507, 126, 90, 3257, 761,
1021, 0, 0, 1636, 0, 228, 1472, 0, 0, 0, 0, 0, 0, 2959, 0, 0,
0, 3203, 0, 99, 0, 3271, 0, 0, 0, 229, 0, 0, 1955, 0, 0, 0,
0, 3905, 3490, 0, 1581, 707, 0, 0, 2685, 0, 2467, 3275, 0, 0, 1525, 668,
0, 0, 1572, 0, 624, 3199, 0, 0, 1465, 348, 0, 0, 0, 0, 2122, 1937,
145, 0, 553, 0, 1649, 0, 939, 3408, 1714, 1982, 0, 3505, 0, 652, 0, 0,
0, 0, 0, 1722, 739, 3343, 0, 2086, 164, 0, 2178, 1870, 0, 0, 0, 0,
0, 3777, 1141, 0, 1240, 0, 403, 0, 919, 345, 0, 1837, 3441, 2900, 0, 0,
0, 0, 2438, 2582, 0, 0, 0, 0, 0, 3725, 0, 3239, 13, 0, 2916, 418,
0, 0, 0, 0, 0, 3898, 0, 0, 0, 0, 0, 0, 0, 1803, 0, 3315,
0, 3371, 0, 0, 0, 2635, 0, 0, 0, 0, 0, 2483, 89, 1416, 0, 1120,
113, 0, 0, 0, 0, 3105, 3619, 2067, 0, 3595, 667, 1957, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 2267, 2682, 0, 0, 823, 2904, 0, 0, 1532, 1288,
0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 509, 2831,
1472, 1384, 0, 0, 0, 0, 0, 3538, 0, 0, 0, 0, 939, 649, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 183, 0, 439,
1363, 0, 0, 0, 0, 1261, 167, 0, 0, 585, 0, 1205, 0, 1748, 0, 0,
0, 0, 418, 3560, 0, 1300, 2694, 0, 0, 2664, 0, 721, 440, 0, 0, 0,
0, 0, 0, 0, 0, 2005, 0, 2661, 0, 0, 2969, 1668, 3659, 0, 0, 0,
0, 0, 0, 539, 0, 2852, 389, 0, 3076, 0, 0, 0, 199, 0, 653, 3319,
0, 3441, 0, 1524, 1795, 2730, 0, 2461, 0, 0, 1838, 0, 0, 712, 1453, 0,
0, 578, 2651, 2172, 1293, 0, 0, 0, 0, 3426, 0, 0, 0, 0, 0, 1997,
0, 0, 0, 79, 0, 319, 1261, 1804, 515, 254, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1728, 0, 714, 2002, 1136, 419, 3847, 0, 0,
983, 0, 1601, 0, 0, 0, 0, 0, 2954, 867, 0, 0, 0, 1, 0, 0,
1426, 0, 0, 2551, 674, 0, 0, 0, 0, 590, 1896, 3333, 0, 0, 76, 0,
0, 0, 0, 1686, 1113, 782, 0, 0, 2809, 0, 817, 0, 3568, 3047, 0, 0,
0, 0, 0, 0, 0, 0, 2110, 424, 3759, 0, 819, 0, 0, 0, 538, 3862,
3618, 2271, 0, 147, 0, 3427, 2291, 0, 0, 806, 2865, 2706, 747, 0, 59, 785,
362, 3006, 521, 0, 0, 0, 0, 0, 3656, 1789, 121, 0, 0, 438, 2029, 0,
0, 1140, 0, 0, 0, 0, 0, 481, 3089, 0, 3837, 2223, 3578, 1776, 114, 0,
0, 0, 0, 0, 0, 3592, 3419, 0, 0, 1302, 3405, 0, 1191, 1243, 0, 3244,
0, 1001, 0, 788, 775, 0, 1230, 331, 0, 0, 0, 1056, 0, 0, 1024, 770,
2927, 0, 0, 1908, 2437, 1227, 3700, 2008, 0, 0, 0, 486, 0, 3654, 510, 311,
1576, 1946, 499, 0, 3328, 0, 3345, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 3287, 0, 0, 0, 2124, 1028, 0, 2645, 0, 0, 0, 0, 3079, 0, 0,
0, 0, 0, 0, 0, 594, 3063, 0, 922, 0, 0, 0, 0, 0, 3878, 1305,
0, 1109, 809, 1113, 0, 1182, 1972, 3154, 0, 812, 3537, 765, 2974, 0, 0, 461,
2776, 1299, 154, 0, 0, 1414, 0, 0, 0, 0, 516, 0, 0, 0, 0, 0,
2040, 0, 1714, 1507, 342, 0, 1988, 2055, 3661, 0, 0, 0, 0, 2785, 1412, 1879,
0, 3373, 0, 0, 0, 2088, 0, 0, 1790, 1015, 108, 714, 0, 1682, 2810, 490,
0, 3173, 0, 3891, 0, 0, 0, 0, 0, 279, 0, 0, 0, 2331, 0, 1997,
3770, 0, 0, 1027, 641, 0, 0, 0, 0, 2318, 0, 0, 0, 0, 3872, 1625,
0, 0, 1529, 0, 0, 2712, 0, 0, 0, 0, 1021, 0, 311, 0, 0, 0,
0, 2172, 464, 0, 2650, 0, 928, 0, 0, 3789, 305, 2715, 0, 0, 1193, 1271,
3874, 2644, 0, 3385, 0, 0, 0, 0, 1490, 178, 0, 507, 672, 98, 0, 2096,
0, 0, 0, 0, 1665, 1400, 0, 0, 0, 0, 2271, 0, 0, 1799, 0, 1619,
635, 330, 0, 0, 1900, 2164, 3653, 3699, 1122, 2498, 0, 0, 1377, 2948, 312, 1839,
0, 0, 3339, 141, 2544, 0, 0, 202, 2477, 0, 0, 348, 0, 0, 342, 0,
2349, 1066, 2276, 1009, 2098, 0, 0, 0, 0, 0, 938, 0, 0, 2266, 0, 2053,
0, 599, 0, 625, 0, 484, 2286, 0, 0, 1868, 3454, 0, 3515, 255, 1430, 3151,
0, 0, 0, 528, 706, 1932, 0, 0, 0, 0, 284, 0, 3450, 0, 0, 0,
771, 0, 2967, 581, 2852, 0, 0, 0, 0, 0, 0, 0, 2581, 1519, 0, 0,
1166, 0, 0, 0, 995, 809, 0, 0, 1808, 0, 0, 0, 0, 0, 0, 0,
0, 2252, 0, 1591, 0, 3647, 2020, 2795, 0, 0, 0, 3548, 0, 87, 2696, 3437,
0, 0, 0, 0, 3307, 386, 2148, 0, 1410, 0, 0, 3563, 3214, 0, 0, 2237,
3841, 0, 460, 1552, 1760, 0, 0, 880, 0, 0, 0, 2334, 1238, 1715, 1377, 2120,
2163, 2977, 0, 975, 310, 2851, 121, 54, 0, 2615, 2871, 1075, 0, 0, 1078, 729,
0, 0, 0, 0, 1433, 485, 3878, 747, 258, 0, 3380, 1, 2026, 0, 0, 214,
930, 2275, 0, 0, 1366, 0, 0, 0, 841, 736, 0, 1684, 0, 0, 0, 1745,
0, 240, 0, 3546, 803, 0, 3718, 0, 807, 0, 2571, 0, 0, 2467, 0, 1902,
2917, 1247, 2118, 1237, 0, 3107, 0, 3576, 0, 0, 1562, 0, 0, 1312, 0, 0,
2517, 1033, 0, 1322, 1074, 3684, 0, 0, 3254, 0, 307, 0, 0, 2719, 0, 0,
0, 2187, 3408, 0, 78, 1464, 0, 2222, 1115, 1624, 0, 1855, 1266, 3276, 268, 2526,
3708, 0, 2430, 0, 890, 595, 1035, 0, 0, 669, 573, 1333, 107, 0, 2816, 1840,
2115, 488, 1146, 1486, 297, 1451, 0, 1244, 2406, 1924, 3684, 58, 0, 0, 894, 0,
188, 3549, 552, 1100, 2625, 1846, 0, 0, 3521, 2174, 0, 2721, 1558, 3120, 0, 0,
2208, 2541, 0, 0, 0, 141, 0, 0, 3506, 1495, 1346, 0, 0, 0, 3461, 212,
1489, 549, 414, 0, 339, 747, 0, 0, 1957, 397, 0, 662, 0, 3477, 0, 1961,
0, 1084, 0, 3398, 3829, 2167, 0, 530, 259, 2781, 1990, 591, 1968, 0, 0, 3183,
2938, 0, 55, 1744, 0, 1974, 1191, 3682, 0, 1782, 437, 0, 0, 0, 0, 0,
2625, 1928, 0, 3838, 0, 0, 3330, 2157, 1872, 170, 62, 0, 607, 0, 157, 0,
1071, 622, 0, 0, 2132, 3654, 0, 0, 1935, 327, 1581, 580, 0, 1381, 0, 286,
0, 595, 2217, 0, 0, 3586, 655, 1765, 0, 0, 0, 2344, 0, 1590, 0, 0,
0, 378, 1438, 0, 9, 703, 1667, 796, 0, 0, 1331, 0, 0, 30, 1701, 3164,
0, 0, 1105, 3487, 1977, 0, 0, 0, 2388, 328, 0, 0, 0, 730, 0, 164,
649, 0, 1487, 0, 0, 0, 3366, 142, 0, 1265, 453, 1317, 0, 0, 0, 2020,
1291, 1774, 0, 1984, 1984, 1576, 1253, 1653, 67, 0, 0, 0, 0, 3866, 2193, 1013,
2036, 1504, 0, 0, 3475, 2681, 0, 151, 0, 1514, 1431, 0, 0, 657, 2430, 1138,
0, 511, 0, 2833, 0, 0, 2112, 335, 437, 0, 1633, 3443, 2263, 0, 1891, 0,
0, 0, 1426, 0, 1462, 2534, 0, 0, 3091, 3074, 2969, 434, 3606, 2203, 2853, 1105,
3404, 0, 2894, 1003, 0, 0, 0, 0, 3053, 0, 0, 1018, 324, 53, 0, 0,
993, 1920, 1174, 0, 0, 2614, 2154, 1508, 0, 176, 0, 3584, 0, 2745, 1274, 3882,
40, 910, 242, 0, 3341, 1565, 2489, 1281, 1825, 3868, 2693, 1526, 58, 823, 989, 2683,
1402, 0, 0, 0, 96, 2765, 0, 0, 0, 3060, 0, 3776, 1190, 0, 940, 3630,
0, 0, 1074, 0, 25, 167, 2251, 0, 0, 0, 0, 0, 1588, 1696, 0, 0,
0, 0, 926, 2770, 1579, 643, 0, 1860, 0, 3599, 0, 0, 0, 116, 2838, 754,
0, 0, 0, 3847, 662, 876, 638, 0, 816, 0, 2532, 0, 0, 0, 371, 0,
2114, 0, 523, 2881, 1323, 3508, 293, 830, 2124, 568, 997, 3062, 0, 3863, 2706, 0,
0, 894, 0, 2193, 0, 0, 184, 1404, 0, 0, 0, 0, 3189, 253, 0, 0,
3694, 540, 1528, 2066, 452, 1549, 1043, 2089, 0, 2618, 2504, 0, 439, 390, 0, 676,
1306, 708, 0, 1607, 1228, 0, 1921, 0, 0, 2589, 0, 46, 0, 0, 1555, 3473,
0, 344, 425, 566, 0, 0, 0, 3027, 1559, 2084, 1538, 1544, 2157, 0, 582, 0,
0, 1466, 0, 1250, 0, 7, 2837, 0, 0, 1090, 0, 0, 0, 774, 1477, 1600,
0, 0, 0, 3459, 3302, 0, 0, 0, 0, 190, 1801, 2743, 1834, 0, 3320, 0,
2091, 0, 899, 0, 3183, 1024, 1614, 0, 2488, 0, 0, 154, 268, 0, 0, 83,
0, 1745, 1523, 0, 773, 0, 1889, 1660, 2226, 0, 2782, 1363, 1560, 0, 0, 3536,
0, 1455, 0, 3786, 0, 1633, 389, 1760, 3249, 1327, 1644, 3337, 260, 30, 489, 1547,
1877, 1680, 1355, 0, 0, 0, 2458, 645, 2136, 190, 1110, 0, 0, 0, 0, 0,
0, 1252, 0, 0, 0, 0, 0, 681, 2637, 326, 0, 677, 608, 2220, 3389, 1820,
1072, 1843, 634, 0, 0, 0, 0, 3307, 0, 3480, 0, 1685, 0, 0, 0, 0,
1697, 3004, 2594, 409, 937, 0, 0, 624, 3473, 0, 0, 1992, 1286, 1828, 0, 0,
1328, 0, 980, 3624, 0, 3585, 3883, 3207, 1598, 0, 0, 1417, 0, 2660, 2003, 0,
0, 0, 0, 1971, 0, 431, 160, 512, 1344, 879, 0, 1261, 1499, 3399, 1480, 0,
0, 0, 3234, 0, 0, 1557, 0, 0, 0, 2065, 0, 143, 729, 910, 1169, 1356,
0, 0, 0, 1685, 0, 0, 732, 0, 2934, 708, 0, 0, 33, 478, 3397, 0,
2913, 2560, 2150, 689, 3030, 3486, 0, 2549, 989, 0, 2302, 386, 133, 1822, 498, 3831,
245, 0, 2317, 671, 0, 0, 3008, 0, 0, 0, 746, 5, 0, 2406, 472, 333,
0, 3753, 0, 0, 0, 1925, 0, 1218, 2106, 121, 0, 328, 563, 1027, 0, 54,
0, 0, 2883, 3358, 0, 213, 1361, 0, 0, 1238, 0, 0, 3229, 0, 2560, 1184,
1880, 3657, 0, 0, 0, 0, 3087, 1568, 3218, 985, 1336, 1869, 0, 3434, 0, 0,
0, 1757, 0, 475, 3499, 2219, 1580, 3237, 1418, 1505, 310, 2161, 980, 2769, 0, 0,
0, 0, 2272, 1200, 0, 0, 0, 0, 1541, 2400, 3207, 269, 0, 206, 1443, 1347,
0, 0, 0, 0, 312, 1785, 644, 0, 2504, 2493, 0, 1076, 2497, 1872, 0, 725,
2926, 2842, 2080, 0, 3828, 2665, 1042, 1405, 0, 825, 0, 0, 2313, 0, 2547, 1065,
0, 2745, 0, 2037, 173, 1974, 0, 0, 3615, 0, 605, 2285, 555, 0, 3274, 0,
0, 0, 1549, 127, 3607, 1415, 0, 532, 943, 3182, 0, 0, 0, 147, 0, 2142,
945, 0, 566, 0, 2092, 0, 0, 0, 2292, 2637, 0, 858, 2858, 3040, 0, 0,
0, 755, 0, 486, 0, 0, 0, 2010, 0, 3631, 791, 3405, 2056, 0, 0, 0,
0, 0, 946, 0, 1929, 1439, 2116, 817, 44, 0, 830, 94, 0, 2172, 0, 3685,
968, 1809, 421, 1808, 1618, 3014, 1681, 0, 2805, 0, 0, 289, 0, 141, 0, 0,
0, 1411, 0, 0, 3143, 0, 0, 0, 2666, 1439, 2091, 567, 3348, 0, 0, 0,
1414, 2787, 0, 1498, 0, 0, 7, 523, 3355, 3125, 1059, 0, 0, 0, 954, 1610,
1687, 762, 0, 0, 0, 2369, 348, 0, 0, 0, 1203, 2456, 1970, 1858, 0, 2015,
0, 0, 877, 69, 1226, 1072, 0, 0, 0, 2095, 1403, 0, 0, 0, 668, 3612,
0, 0, 1594, 0, 2643, 766, 3114, 818, 1628, 1941, 967, 0, 1388, 148, 747, 0,
2370, 0, 1365, 0, 0, 2177, 0, 0, 0, 2164, 2861, 0, 1996, 0, 912, 2959,
1091, 0, 3774, 54, 1024, 0, 3199, 0, 1540, 1124, 0, 1514, 0, 3612, 733, 3337,
0, 0, 0, 0, 0, 235, 1998, 758, 0, 1710, 198, 2035, 0, 0, 0, 0,
491, 0, 3457, 0, 0, 3529, 0, 2050, 1952, 3160, 0, 2274, 222, 504, 229, 741,
149, 0, 1725, 3292, 1611, 3612, 2868, 670, 1860, 1263, 1799, 45, 0, 1232, 3012, 0,
0, 3804, 0, 1911, 0, 2892, 1199, 74, 612, 3313, 0, 0, 0, 0, 3813, 1287,
543, 505, 2171, 0, 2137, 2677, 0, 534, 2754, 369, 0, 3887, 0, 996, 1821, 0,
381, 987, 0, 1960, 1148, 0, 1661, 3585, 564, 0, 147, 2705, 0, 0, 0, 1950,
671, 0, 0, 0, 2105, 0, 1662, 1792, 1356, 2560, 1450, 2661, 0, 831, 646, 0,
82, 0, 0, 2709, 798, 0, 1885, 3763, 0, 1982, 2024, 3416, 313, 1968, 3605, 2845,
541, 2233, 0, 0, 0, 2112, 1871, 0, 1299, 217, 0, 0, 0, 757, 0, 0,
1629, 2175, 2014, 778, 1940, 728, 2891, 0, 0, 310, 898, 1280, 0, 902, 3741, 3256,
338, 0, 0, 0, 0, 3031, 3048, 2660, 1980, 0, 776, 1848, 0, 550, 432, 1991,
276, 0, 0, 0, 0, 0, 2115, 2554, 2887, 924, 1089, 0, 403, 0, 630, 2970,
0, 630, 2171, 1758, 0, 957, 66, 760, 1864, 1895, 853, 357, 0, 0, 1256, 0,
0, 253, 0, 0, 3066, 2879, 0, 0, 1735, 3384, 0, 1650, 352, 2055, 626, 1650,
0, 2663, 0, 0, 118, 0, 2063, 0, 1340, 3276, 1134, 656, 0, 0, 0, 2907,
3145, 963, 1043, 2803, 0, 0, 870, 1546, 691, 411, 3305, 2004, 0, 3085, 1348, 0,
81, 0, 2192, 0, 3051, 1513, 1197, 0, 738, 2285, 0, 2710, 0, 0, 315, 0,
0, 1066, 693, 3121, 3873, 3821, 2158, 1937, 0, 1668, 0, 0, 0, 3215, 3184, 2628,
2929, 560, 736, 0, 1279, 3307, 401, 1980, 1419, 3414, 2345, 0, 0, 0, 2126, 3536,
1576, 1025, 0, 3899, 0, 593, 2388, 0, 0, 2878, 0, 30, 1304, 1411, 0, 824,
3308, 0, 2800, 0, 3419, 530, 3650, 3056, 129, 3508, 718, 2084, 0, 0, 1391, 95,
864, 3364, 3646, 0, 1736, 3174, 572, 531, 0, 3219, 696, 3303, 0, 116, 2058, 0,
0, 904, 0, 0, 1528, 0, 1284, 2919, 1815, 0, 0, 1275, 0, 3777, 1331, 266,
805, 2729, 7, 0, 3511, 0, 1050, 3896, 0, 0, 0, 1379, 1597, 118, 1269, 3567,
3067, 0, 3682, 1070, 0, 287, 1694, 51, 3826, 0, 353, 2215, 0, 3597, 1664, 381,
1885, 0, 2133, 1741, 907, 0, 2021, 0, 0, 0, 0, 827, 1859, 3419, 2267, 3346,
0, 2661, 1507, 719, 188, 258, 2896, 0, 660, 2748, 3908, 927, 0, 2973, 0, 2356,
3597, 349, 3040, 2150, 3437, 2596, 1166, 206, 2153, 3885, 1962, 471, 99, 2018, 2351, 0,
0, 2136, 2013, 3900, 3828, 2895, 2310, 975, 0, 204, 3731, 1341, 1676, 3773, 0, 1817,
0, 3099, 3719, 1093, 1122, 349, 578, 0, 2159, 0, 0, 965, 2446, 3540, 0, 872,
3170, 1704, 1105, 0, 1657, 470, 0, 0, 1645, 2740, 0, 2513, 3890, 1373, 356, 0,
57, 2310, 744, 0, 0, 1520, 2129, 1214, 0, 0, 2026, 2436, 267, 2260, 0, 0,
2227, 3562, 0, 943, 1927, 1150, 0, 3841, 1749, 964, 2005, 0, 3896, 0, 0, 2655,
354, 0, 0, 2774, 0, 2069, 0, 52, 0, 479, 0, 430, 1919, 2225, 900, 1119,
571, 1158, 1465, 1946, 1252, 3402, 480, 0, 0, 0, 1231, 481, 0, 1444, 2766, 1581,
2660, 3535, 0, 0, 71, 3828, 1713, 0, 1228, 2136, 1183, 0, 1781, 734, 0, 3700,
3534, 0, 73, 0, 1702, 1914, 0, 601, 0, 0, 1530, 0, 2405, 1796, 902, 0,
0, 0, 2080, 2759, 0, 3003, 0, 810, 0, 0, 0, 1024, 0, 3509, 0, 1845,
3854, 3617, 1575, 0, 1653, 1474, 1763, 0, 0, 109, 1008, 2871, 0, 0, 871, 3113,
0, 208, 2571, 0, 2060, 0, 0, 877, 3689, 1367, 3365, 0, 0, 0, 84, 0,
1296, 1430, 1322, 0, 0, 0, 1705, 2535, 1659, 533, 3172, 3362, 655, 3207, 0, 974,
1740, 1011, 0, 0, 0, 0, 0, 1706, 427, 2762, 2834, 2918, 1449, 197, 0, 881,
276, 3690, 182, 567, 1062, 75, 3783, 0, 701, 0, 1463, 1775, 0, 0, 2743, 0,
265, 352, 0, 0, 1187, 0, 1078, 0, 798, 2790, 0, 2276, 0, 3087, 2903, 0,
690, 617, 3324, 1907, 2568, 2987, 1225, 3342, 0, 1081, 914, 496, 0, 1238, 1921, 0,
3602, 0, 2073, 0, 3743, 0, 3197, 0, 742, 3730, 1016, 467, 42, 2277, 0, 0,
1189, 2181, 920, 0, 0, 0, 0, 503, 3603, 2242, 0, 2165, 0, 3791, 0, 2397,
0, 0, 1277, 774, 1326, 662, 0, 525, 1959, 90, 610, 1015, 1303, 0, 1756, 0,
1068, 1337, 2179, 2096, 0, 0, 1807, 0, 3641, 1764, 1873, 3383, 3180, 67, 1999, 0,
927, 82, 0, 0, 0, 1021, 1320, 3492, 498, 1749, 798, 1140, 0, 2955, 1506, 422,
1869, 261, 0, 0, 1080, 0, 392, 0, 181, 0, 0, 2624, 0, 2855, 2930, 1950,
0, 716, 0, 3164, 3521, 1209, 1224, 0, 515, 755, 0, 1088, 404, 1554, 3163, 388,
3497, 699, 1141, 3907, 2468, 1613, 767, 977, 24, 0, 1019, 0, 3655, 0, 81, 0,
1086, 1587, 1434, 0, 1023, 3477, 1920, 2071, 251, 1403, 0, 3717, 223, 0, 0, 3864,
323, 0, 0, 182, 0, 2562, 210, 56, 1545, 1185, 827, 2422, 423, 2662, 1661, 0,
0, 190, 0, 2212, 0, 1850, 3772, 703, 14, 0, 0, 3784, 2944, 0, 959, 0,
1727, 0, 2523, 3024, 1859, 813, 1492, 2584, 2367, 0, 0, 0, 0, 3672, 0, 3408,
0, 1059, 758, 3851, 0, 3380, 186, 0, 1456, 1945, 3306, 0, 980, 3814, 3502, 2483,
2911, 273, 373, 187, 559, 1561, 754, 826, 0, 1820, 131, 0, 2173, 0, 0, 429,
1648, 3559, 0, 0, 0, 0, 0, 2707, 1442, 2893, 0, 3316, 936, 0, 1240, 1415,
855, 0, 1202, 301, 0, 0, 2133, 0, 2827, 0, 913, 1449, 3410, 1008, 0, 306,
2880, 1846, 0, 1986, 1340, 0, 0, 0, 3355, 712, 2137, 0, 731, 61, 0, 3632,
724, 1243, 1201, 0, 1017, 561, 1059, 2140, 1769, 1444, 914, 724, 3618, 2489, 1167, 0,
0, 1207, 0, 215, 3106, 2726, 0, 0, 0, 0, 0, 1139, 1496, 0, 1097, 408,
2186, 1804, 3501, 462, 3824, 0, 1498, 1093, 1894, 1044, 0, 1894, 2699, 1002, 0, 1605,
3767, 1623, 420, 2928, 0, 0, 0, 0, 0, 194, 0, 553, 0, 1258, 0, 1384,
1262, 2343, 159, 1166, 0, 2950, 2985, 0, 1557, 0, 370, 3826, 951, 1014, 0, 1248,
0, 256, 0, 2223, 2550, 0, 2354, 0, 1596, 0, 0, 53, 1748, 1394, 3210, 1303,
0, 0, 0, 3421, 0, 1579, 2151, 1638, 3326, 451, 1783, 1130, 2761, 1071, 602, 0,
1461, 0, 1261, 146, 0, 612, 0, 0, 1987, 862, 3804, 211, 557, 0, 0, 970,
0, 0, 2009, 2873, 53, 2946, 2721, 658, 677, 686, 0, 3845, 2272, 0, 0, 0,
1642, 0, 0, 649, 2968, 2372, 470, 2019, 14, 1282, 0, 3017, 663, 0, 1307, 507,
483, 322, 966, 0, 3758, 3677, 0, 0, 1198, 3872, 2397, 0, 0, 273, 0, 1595,
0, 660, 446, 1041, 2558, 2345, 1285, 0, 0, 2606, 227, 0, 3494, 1706, 1054, 3798,
0, 3024, 0, 0, 1864, 0, 0, 1724, 3572, 3326, 0, 0, 0, 72, 448, 0,
1807, 0, 1036, 3814, 2835, 0, 0, 1834, 3346, 1822, 2014, 691, 0, 0, 0, 0,
499, 671, 3731, 0, 803, 3524, 447, 743, 456, 3187, 1880, 2288, 0, 103, 341, 820,
3732, 0, 216, 441, 2269, 1746, 1108, 0, 1920, 0, 0, 253, 1574, 209, 1316, 648,
1705, 0, 0, 1741, 3656, 236, 0, 3907, 2044, 2384, 1192, 967, 465, 3320, 1482, 1918,
612, 1984, 2204, 2179, 1628, 589, 1853, 387, 2568, 0, 813, 0, 1426, 3412, 979, 3024,
1949, 0, 351, 0, 0, 0, 0, 2063, 0, 1129, 0, 1539, 1706, 127, 0, 1360,
1251, 3282, 1796, 241, 0, 817, 0, 1164, 463, 2587, 0, 722, 0, 0, 0, 3508,
0, 0, 311, 1137, 2757, 0, 353, 252, 0, 0, 0, 0, 589, 0, 0, 1,
420, 2962, 0, 2525, 2255, 596, 74, 3907, 0, 0, 0, 0, 0, 1914, 0, 3602,
2121, 0, 0, 3874, 0, 1719, 507, 1669, 0, 0, 532, 0, 1066, 949, 684, 2948,
405, 0, 0, 0, 1387, 564, 175, 1626, 0, 0, 0, 0, 494, 2886, 104, 938,
0, 3751, 714, 526, 0, 66, 1684, 0, 1127, 3173, 1399, 2581, 0, 41, 792, 0,
0, 1259, 636, 0, 1738, 1800, 0, 2810, 530, 1135, 680, 1594, 814, 1246, 2115, 0,
0, 0, 0, 0, 2162, 2633, 1089, 20, 0, 3347, 483, 0, 0, 849, 971, 0,
632, 1309, 2010, 3895, 0, 355, 1501, 784, 1264, 601, 1155, 0, 1912, 0, 0, 1689,
0, 587, 321, 0, 0, 1382, 1924, 885, 3902, 592, 1573, 1272, 869, 97, 1802, 835,
254, 397, 1062, 206, 3234, 0, 548, 0, 1454, 0, 2301, 3788, 3143, 2236, 3351, 1649,
1942, 3752, 0, 0, 238, 510, 1887, 2196, 3172, 309, 1591, 0, 3621, 0, 1143, 0,
810, 0, 0, 0, 0, 0, 514, 0, 0, 0, 1694, 1164, 1604, 235, 0, 3901,
0, 1753, 3618, 1588, 2160, 710, 658, 0, 0, 2379, 1425, 555, 0, 321, 0, 0,
1282, 1163, 0, 0, 0, 0, 3295, 1975, 0, 3559, 833, 3879, 0, 2102, 0, 0,
513, 3788, 1223, 1180, 2652, 0, 0, 3435, 0, 115, 0, 1107, 2205, 0, 0, 546,
3482, 558, 739, 0, 867, 3554, 1071, 0, 1405, 0, 1015, 1590, 0, 104, 3139, 0,
1186, 0, 733, 0, 0, 0};
1470, 1386, 0, 0, 0, 0, 0, 3542, 0, 0, 0, 0, 941, 647, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 183, 0, 439,
1365, 0, 0, 0, 0, 1267, 169, 0, 0, 589, 0, 1205, 0, 1746, 0, 0,
0, 0, 418, 3562, 0, 1306, 2694, 0, 0, 2666, 0, 711, 440, 0, 0, 0,
0, 0, 0, 0, 0, 2007, 0, 2659, 0, 0, 2967, 1670, 3660, 0, 0, 0,
0, 0, 0, 529, 0, 2850, 389, 0, 3076, 0, 0, 0, 199, 0, 650, 3319,
0, 3439, 0, 1526, 1797, 2726, 0, 2465, 0, 0, 1840, 0, 0, 711, 1455, 0,
0, 578, 2651, 2175, 1295, 0, 0, 0, 0, 3429, 0, 0, 0, 0, 0, 1999,
0, 0, 0, 79, 0, 319, 1263, 1806, 515, 254, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1730, 0, 713, 2006, 1138, 417, 3845, 0, 0,
985, 0, 1603, 0, 0, 0, 0, 0, 2962, 869, 0, 0, 0, 5, 0, 0,
1428, 0, 0, 2553, 672, 0, 0, 0, 0, 582, 1898, 3333, 0, 0, 76, 0,
0, 0, 0, 1688, 1117, 786, 0, 0, 2811, 0, 821, 0, 3568, 3053, 0, 0,
0, 0, 0, 0, 0, 0, 2107, 426, 3759, 0, 817, 0, 0, 0, 538, 3868,
3616, 2275, 0, 147, 0, 3419, 2289, 0, 0, 803, 2863, 2706, 747, 0, 64, 787,
360, 3011, 521, 0, 0, 0, 0, 0, 3658, 1791, 121, 0, 0, 438, 2027, 0,
0, 1142, 0, 0, 0, 0, 0, 483, 3089, 0, 3837, 2221, 3576, 1778, 124, 0,
0, 0, 0, 0, 0, 3590, 3419, 0, 0, 1304, 3407, 0, 1193, 1245, 0, 3248,
0, 1003, 0, 786, 777, 0, 1228, 333, 0, 0, 0, 1062, 0, 0, 1024, 774,
2925, 0, 0, 1906, 2437, 1227, 3700, 2010, 0, 0, 0, 486, 0, 3652, 510, 313,
1582, 1948, 503, 0, 3330, 0, 3348, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 3290, 0, 0, 0, 2124, 1028, 0, 2643, 0, 0, 0, 0, 3077, 0, 0,
0, 0, 0, 0, 0, 596, 3065, 0, 922, 0, 0, 0, 0, 0, 3874, 1305,
0, 1111, 813, 1115, 0, 1184, 1964, 3150, 0, 808, 3539, 767, 2972, 0, 0, 461,
2776, 1303, 154, 0, 0, 1416, 0, 0, 0, 0, 518, 0, 0, 0, 0, 0,
2042, 0, 1712, 1511, 342, 0, 1990, 2059, 3659, 0, 0, 0, 0, 2782, 1414, 1881,
0, 3371, 0, 0, 0, 2084, 0, 0, 1786, 1019, 108, 716, 0, 1682, 2810, 480,
0, 3171, 0, 3887, 0, 0, 0, 0, 0, 279, 0, 0, 0, 2335, 0, 1995,
3770, 0, 0, 1029, 643, 0, 0, 0, 0, 2322, 0, 0, 0, 0, 3874, 1625,
0, 0, 1531, 0, 0, 2710, 0, 0, 0, 0, 1015, 0, 317, 0, 0, 0,
0, 2162, 544, 0, 2650, 0, 926, 0, 0, 3711, 305, 2715, 0, 0, 1195, 1271,
3872, 2646, 0, 3395, 0, 0, 0, 0, 1492, 178, 0, 507, 676, 88, 0, 2096,
0, 0, 0, 0, 1663, 1404, 0, 0, 0, 0, 2269, 0, 0, 1805, 0, 1619,
635, 330, 0, 0, 1902, 2164, 3651, 3695, 1124, 2496, 0, 0, 1379, 2948, 314, 1841,
0, 0, 3342, 141, 2544, 0, 0, 202, 2473, 0, 0, 348, 0, 0, 339, 0,
2353, 1068, 2276, 1011, 2102, 0, 0, 0, 0, 0, 940, 0, 0, 2268, 0, 2047,
0, 601, 0, 631, 0, 484, 2284, 0, 0, 1870, 3464, 0, 3515, 255, 1430, 3149,
0, 0, 0, 528, 704, 1934, 0, 0, 0, 0, 284, 0, 3450, 0, 0, 0,
771, 0, 2971, 579, 2851, 0, 0, 0, 0, 0, 0, 0, 2585, 1519, 0, 0,
1158, 0, 0, 0, 995, 809, 0, 0, 1810, 0, 0, 0, 0, 0, 0, 0,
0, 2256, 0, 1593, 0, 3647, 2022, 2789, 0, 0, 0, 3550, 0, 87, 2698, 3443,
0, 0, 0, 0, 3311, 386, 2148, 0, 1412, 0, 0, 3563, 3210, 0, 0, 2245,
3845, 0, 458, 1550, 1762, 0, 0, 878, 0, 0, 0, 2336, 1238, 1711, 1377, 2122,
2163, 2979, 0, 973, 316, 2853, 123, 58, 0, 2619, 2875, 1077, 0, 0, 1070, 729,
0, 0, 0, 0, 1437, 489, 3878, 751, 264, 0, 3380, 1, 2028, 0, 0, 214,
932, 2273, 0, 0, 1372, 0, 0, 0, 839, 748, 0, 1690, 0, 0, 0, 1747,
0, 240, 0, 3548, 805, 0, 3716, 0, 809, 0, 2569, 0, 0, 2469, 0, 1904,
2922, 1245, 2118, 1237, 0, 3105, 0, 3580, 0, 0, 1564, 0, 0, 1320, 0, 0,
2515, 1035, 0, 1324, 1071, 3684, 0, 0, 3252, 0, 307, 0, 0, 2721, 0, 0,
0, 2185, 3408, 0, 78, 1466, 0, 2222, 1117, 1626, 0, 1853, 1268, 3280, 258, 2524,
3712, 0, 2428, 0, 890, 595, 1039, 0, 0, 665, 579, 1331, 105, 0, 2812, 1832,
2117, 488, 1148, 1488, 297, 1453, 0, 1242, 2410, 1926, 3682, 54, 0, 0, 892, 0,
188, 3546, 552, 1102, 2633, 1845, 0, 0, 3521, 2174, 0, 2719, 1555, 3124, 0, 0,
2206, 2535, 0, 0, 0, 143, 0, 0, 3502, 1497, 1348, 0, 0, 0, 3461, 212,
1491, 551, 414, 0, 344, 749, 0, 0, 1961, 397, 0, 662, 0, 3477, 0, 1963,
0, 1088, 0, 3396, 3829, 2167, 0, 532, 259, 2775, 1992, 593, 1968, 0, 0, 3184,
2936, 0, 55, 1746, 0, 1972, 1193, 3680, 0, 1784, 437, 0, 0, 0, 0, 0,
2625, 1930, 0, 3836, 0, 0, 3330, 2159, 1869, 170, 64, 0, 607, 0, 157, 0,
1073, 622, 0, 0, 2132, 3656, 0, 0, 1931, 327, 1583, 580, 0, 1381, 0, 288,
0, 599, 2219, 0, 0, 3590, 653, 1767, 0, 0, 0, 2342, 0, 1588, 0, 0,
0, 378, 1428, 0, 9, 711, 1669, 796, 0, 0, 1333, 0, 0, 30, 1703, 3162,
0, 0, 1101, 3487, 1983, 0, 0, 0, 2392, 328, 0, 0, 0, 730, 0, 162,
739, 0, 1497, 0, 0, 0, 3366, 142, 0, 1263, 451, 1319, 0, 0, 0, 2022,
1291, 1776, 0, 1984, 1982, 1576, 1255, 1655, 70, 0, 0, 0, 0, 3866, 2191, 1015,
2038, 1504, 0, 0, 3477, 2677, 0, 151, 0, 1516, 1431, 0, 0, 653, 2434, 1138,
0, 509, 0, 2835, 0, 0, 2112, 335, 433, 0, 1631, 3443, 2261, 0, 1897, 0,
0, 0, 1426, 0, 1464, 2532, 0, 0, 3093, 3078, 2967, 436, 3605, 2205, 2857, 1101,
3408, 0, 2890, 1005, 0, 0, 0, 0, 3051, 0, 0, 1014, 324, 51, 0, 0,
995, 1922, 1176, 0, 0, 2618, 2154, 1512, 0, 166, 0, 3584, 0, 2745, 1286, 3882,
40, 912, 242, 0, 3341, 1567, 2491, 1281, 1831, 3868, 2689, 1528, 58, 825, 989, 2677,
1404, 0, 0, 0, 98, 2767, 0, 0, 0, 3064, 0, 3778, 1192, 0, 942, 3630,
0, 0, 1076, 0, 30, 167, 2250, 0, 0, 0, 0, 0, 1587, 1698, 0, 0,
0, 0, 928, 2768, 1581, 639, 0, 1858, 0, 3597, 0, 0, 0, 116, 2842, 756,
0, 0, 0, 3849, 660, 879, 638, 0, 814, 0, 2534, 0, 0, 0, 369, 0,
2114, 0, 523, 2887, 1325, 3512, 293, 834, 2128, 573, 999, 3072, 0, 3863, 2712, 0,
0, 896, 0, 2199, 0, 0, 188, 1406, 0, 0, 0, 0, 3189, 257, 0, 0,
3690, 540, 1530, 2066, 452, 1547, 1045, 2083, 0, 2612, 2502, 0, 441, 390, 0, 676,
1300, 706, 0, 1609, 1230, 0, 1923, 0, 0, 2587, 0, 44, 0, 0, 1555, 3473,
0, 340, 427, 563, 0, 0, 0, 3031, 1559, 2084, 1540, 1550, 2157, 0, 582, 0,
0, 1464, 0, 1250, 0, 3908, 2841, 0, 0, 1092, 0, 0, 0, 768, 1479, 1602,
0, 0, 0, 3449, 3306, 0, 0, 0, 0, 194, 1795, 2751, 1836, 0, 3238, 0,
2091, 0, 897, 0, 3185, 1026, 1616, 0, 2486, 0, 0, 156, 268, 0, 0, 81,
0, 1743, 1525, 0, 775, 0, 1891, 1656, 2228, 0, 2783, 1365, 1562, 0, 0, 3528,
0, 1455, 0, 3796, 0, 1634, 387, 1760, 3247, 1337, 1646, 3333, 260, 35, 491, 1549,
1879, 1672, 1357, 0, 0, 0, 2456, 645, 2140, 192, 1106, 0, 0, 0, 0, 0,
0, 1250, 0, 0, 0, 0, 0, 679, 2641, 326, 0, 675, 604, 2214, 3391, 1822,
1074, 1845, 634, 0, 0, 0, 0, 3311, 0, 3483, 0, 1687, 0, 0, 0, 0,
1701, 3010, 2594, 415, 939, 0, 0, 624, 3477, 0, 0, 1994, 1284, 1842, 0, 0,
1330, 0, 982, 3630, 0, 3585, 3883, 3207, 1600, 0, 0, 1419, 0, 2658, 2005, 0,
0, 0, 0, 1973, 0, 431, 160, 510, 1346, 881, 0, 1261, 1499, 3397, 1482, 0,
0, 0, 3236, 0, 0, 1559, 0, 0, 0, 2065, 0, 143, 729, 908, 1171, 1358,
0, 0, 0, 1685, 0, 0, 732, 0, 2934, 708, 0, 0, 33, 478, 3400, 0,
2913, 2564, 2150, 687, 3022, 3486, 0, 2547, 991, 0, 2300, 390, 131, 1820, 498, 3831,
245, 0, 2315, 667, 0, 0, 3006, 0, 0, 0, 746, 5, 0, 2404, 474, 333,
0, 3753, 0, 0, 0, 1927, 0, 1216, 2106, 119, 0, 330, 563, 1027, 0, 54,
0, 0, 2879, 3356, 0, 213, 1361, 0, 0, 1238, 0, 0, 3233, 0, 2562, 1186,
1882, 3657, 0, 0, 0, 0, 3085, 1568, 3214, 985, 1338, 1871, 0, 3436, 0, 0,
0, 1757, 0, 475, 3499, 2219, 1582, 3237, 1424, 1507, 314, 2159, 980, 2771, 0, 0,
0, 0, 2266, 1197, 0, 0, 0, 0, 1541, 2404, 3205, 269, 0, 208, 1445, 1345,
0, 0, 0, 0, 312, 1781, 644, 0, 2507, 2489, 0, 1078, 2501, 1876, 0, 725,
2924, 2840, 2080, 0, 3838, 2667, 1046, 1404, 0, 827, 0, 0, 2309, 0, 2549, 1067,
0, 2745, 0, 2039, 171, 1976, 0, 0, 3610, 0, 613, 2287, 557, 0, 3272, 0,
0, 0, 1551, 133, 3610, 1417, 0, 524, 941, 3180, 0, 0, 0, 151, 0, 2146,
947, 0, 568, 0, 2094, 0, 0, 0, 2292, 2643, 0, 860, 2854, 3046, 0, 0,
0, 759, 0, 486, 0, 0, 0, 2012, 0, 3629, 793, 3403, 2058, 0, 0, 0,
0, 0, 936, 0, 1931, 1441, 2118, 816, 44, 0, 834, 90, 0, 2174, 0, 3685,
974, 1811, 421, 1810, 1620, 3016, 1679, 0, 2801, 0, 0, 291, 0, 141, 0, 0,
0, 1411, 0, 0, 3144, 0, 0, 0, 2668, 1441, 2085, 567, 3350, 0, 0, 0,
1420, 2787, 0, 1500, 0, 0, 7, 523, 3347, 3126, 2393, 0, 0, 0, 956, 1612,
1689, 762, 0, 0, 0, 2367, 348, 0, 0, 0, 1285, 2458, 1974, 1860, 0, 2017,
0, 0, 879, 69, 1226, 1072, 0, 0, 0, 2095, 1401, 0, 0, 0, 666, 3615,
0, 0, 1598, 0, 2641, 768, 3119, 814, 1632, 1943, 971, 0, 1385, 148, 749, 0,
2376, 0, 1367, 0, 0, 2177, 0, 0, 0, 2164, 2859, 0, 1995, 0, 912, 2959,
1087, 0, 3774, 54, 1026, 0, 3199, 0, 1542, 1126, 0, 1518, 0, 3612, 733, 3339,
0, 0, 0, 0, 0, 235, 2000, 760, 0, 1720, 196, 2037, 0, 0, 0, 0,
493, 0, 3460, 0, 0, 3527, 0, 2052, 1954, 3160, 0, 2280, 222, 514, 229, 743,
149, 0, 1727, 3284, 1603, 3612, 2872, 668, 1862, 1263, 1801, 40, 0, 1232, 3012, 0,
0, 3808, 0, 1913, 0, 2890, 1201, 68, 618, 3323, 0, 0, 0, 0, 3813, 1289,
545, 505, 2169, 0, 2137, 2677, 0, 530, 2752, 369, 0, 3887, 0, 998, 1823, 0,
371, 989, 0, 1960, 1148, 0, 1663, 3589, 564, 0, 147, 2704, 0, 0, 0, 1946,
669, 0, 0, 0, 2101, 0, 1658, 1794, 1358, 2556, 1450, 2657, 0, 833, 646, 0,
88, 0, 0, 2707, 800, 0, 1887, 3759, 0, 1980, 2022, 3418, 303, 1970, 3611, 2839,
537, 2235, 0, 0, 0, 2112, 1871, 0, 1301, 217, 0, 0, 0, 759, 0, 0,
1627, 2169, 2014, 780, 1950, 728, 2890, 0, 0, 310, 900, 1280, 0, 904, 3741, 3252,
338, 0, 0, 0, 0, 3031, 3056, 2658, 1982, 0, 778, 1840, 0, 550, 432, 1995,
276, 0, 0, 0, 0, 0, 2117, 2552, 2895, 924, 1091, 0, 405, 0, 630, 2970,
0, 632, 2169, 1762, 0, 959, 66, 762, 1866, 1893, 855, 357, 0, 0, 1256, 0,
0, 255, 0, 0, 3064, 2875, 0, 0, 1735, 3390, 0, 1652, 352, 2057, 626, 1652,
0, 2661, 0, 0, 118, 0, 2064, 0, 1342, 3278, 1134, 654, 0, 0, 0, 2913,
3147, 965, 1045, 2805, 0, 0, 868, 1548, 693, 407, 3305, 2006, 0, 3089, 1350, 0,
77, 0, 2194, 0, 3054, 1515, 1199, 0, 738, 2285, 0, 2712, 0, 0, 315, 0,
0, 1068, 693, 3123, 3873, 3821, 2144, 1939, 0, 1666, 0, 0, 0, 3215, 3186, 2632,
2933, 560, 736, 0, 1277, 3309, 405, 1982, 1421, 3410, 2351, 0, 0, 0, 2132, 3538,
1578, 1025, 0, 3899, 0, 593, 2384, 0, 0, 2882, 0, 28, 1306, 1413, 0, 826,
3308, 0, 2798, 0, 3423, 524, 3654, 3060, 129, 3510, 718, 2086, 0, 0, 1393, 91,
866, 3367, 3652, 0, 1738, 3174, 570, 531, 0, 3217, 696, 3309, 0, 120, 2054, 0,
0, 904, 0, 0, 1528, 0, 1284, 2923, 1817, 0, 0, 1275, 0, 3779, 1333, 266,
805, 2731, 11, 0, 3511, 0, 1052, 3896, 0, 0, 0, 1381, 1599, 118, 1265, 3569,
3065, 0, 3682, 1072, 0, 289, 1696, 51, 3828, 0, 353, 2225, 0, 3597, 1666, 381,
1889, 0, 2133, 1743, 907, 0, 2019, 0, 0, 0, 0, 827, 1857, 3419, 2269, 3342,
0, 2663, 1509, 718, 194, 262, 2894, 0, 656, 2746, 3904, 931, 0, 2971, 0, 2358,
3597, 349, 3036, 2150, 3437, 2594, 1164, 206, 2153, 3880, 1964, 471, 99, 2020, 2351, 0,
0, 2130, 2011, 3898, 3828, 2899, 2310, 977, 0, 204, 3735, 1343, 1678, 3775, 0, 1819,
0, 3099, 3721, 1091, 1122, 351, 578, 0, 2159, 0, 0, 967, 2448, 3540, 0, 874,
3172, 1706, 1095, 0, 1659, 470, 0, 0, 1649, 2742, 0, 2514, 3890, 1371, 356, 0,
59, 2308, 746, 0, 0, 1524, 2131, 1214, 0, 0, 2024, 2444, 259, 2266, 0, 0,
2225, 3564, 0, 945, 1929, 1152, 0, 3845, 1749, 966, 2007, 0, 3900, 0, 0, 2653,
354, 0, 0, 2776, 0, 2069, 0, 52, 0, 485, 0, 428, 1921, 2223, 902, 1119,
568, 1156, 1467, 1950, 1252, 3400, 486, 0, 0, 0, 1231, 481, 0, 1436, 2764, 1583,
2660, 3538, 0, 0, 71, 3828, 1715, 0, 1224, 2135, 1185, 0, 1785, 734, 0, 3704,
3534, 0, 73, 0, 1702, 1908, 0, 601, 0, 0, 1532, 0, 2401, 1798, 896, 0,
0, 0, 2080, 2765, 0, 3003, 0, 812, 0, 0, 0, 1024, 0, 3517, 0, 1847,
3852, 3615, 1567, 0, 1655, 1470, 1775, 0, 0, 107, 1004, 2871, 0, 0, 873, 3113,
0, 208, 2579, 0, 2062, 0, 0, 879, 3691, 1369, 3365, 0, 0, 0, 84, 0,
1298, 1432, 1324, 0, 0, 0, 1709, 2535, 1661, 535, 3170, 3366, 651, 3205, 0, 976,
1742, 1013, 0, 0, 0, 0, 0, 1708, 427, 2760, 2836, 2916, 1451, 197, 0, 881,
274, 3686, 184, 567, 1064, 75, 3783, 0, 704, 0, 1475, 1855, 0, 0, 2739, 0,
267, 348, 0, 0, 1189, 0, 1082, 0, 798, 2788, 0, 2274, 0, 3091, 2903, 0,
686, 617, 3322, 1909, 2570, 2993, 1225, 3342, 0, 1083, 916, 496, 0, 1232, 1923, 0,
3600, 0, 2075, 0, 3831, 0, 3200, 0, 742, 3732, 1016, 471, 42, 2277, 0, 0,
1191, 2180, 922, 0, 0, 0, 0, 507, 3613, 2240, 0, 2165, 0, 3789, 0, 2401,
0, 0, 1279, 776, 1328, 660, 0, 521, 1961, 90, 612, 1017, 1305, 0, 1758, 0,
1070, 1331, 2180, 2095, 0, 0, 1809, 0, 3651, 1766, 1875, 3387, 3182, 73, 2001, 0,
925, 82, 0, 0, 0, 1019, 1320, 3412, 500, 1751, 800, 1142, 0, 2951, 1508, 422,
1868, 263, 0, 0, 1082, 0, 392, 0, 183, 0, 0, 2610, 0, 2853, 2930, 1952,
0, 715, 0, 3168, 3525, 1209, 1224, 0, 515, 753, 0, 1090, 404, 1556, 3167, 388,
3497, 699, 1141, 3907, 2472, 1615, 767, 977, 24, 0, 1024, 0, 3655, 0, 81, 0,
1084, 1591, 1436, 0, 1025, 3481, 1922, 2071, 251, 1403, 0, 3715, 221, 0, 0, 3864,
323, 0, 0, 182, 0, 2565, 208, 56, 1549, 1188, 829, 2422, 423, 2660, 1667, 0,
0, 190, 0, 2206, 0, 1848, 3772, 705, 14, 0, 0, 3784, 2950, 0, 961, 0,
1727, 0, 2523, 3024, 1863, 815, 1496, 2590, 2365, 0, 0, 0, 0, 3672, 0, 3408,
0, 1061, 760, 3855, 0, 3384, 192, 0, 1458, 1947, 3298, 0, 982, 3810, 3502, 2481,
2909, 273, 375, 187, 559, 1563, 756, 836, 0, 1824, 131, 0, 2173, 0, 0, 429,
1650, 3563, 0, 0, 0, 0, 0, 2709, 1440, 2891, 0, 3316, 938, 0, 1246, 1417,
867, 0, 1204, 301, 0, 0, 2131, 0, 2825, 0, 921, 1453, 3408, 1006, 0, 310,
2882, 1848, 0, 1988, 1336, 0, 0, 0, 3351, 720, 2133, 0, 731, 61, 0, 3632,
724, 1247, 1203, 0, 1019, 561, 1059, 2140, 1771, 1446, 916, 724, 3618, 2491, 1163, 0,
0, 1207, 0, 2791, 3104, 2726, 0, 0, 0, 0, 0, 1141, 1498, 0, 1093, 402,
2190, 1806, 3499, 462, 3820, 0, 1494, 1093, 1896, 1046, 0, 1891, 2703, 1004, 0, 1609,
3767, 1621, 420, 2926, 0, 0, 0, 0, 0, 194, 0, 553, 0, 1258, 0, 1384,
1262, 2345, 159, 1168, 0, 2952, 2985, 0, 1559, 0, 368, 3824, 957, 1014, 0, 1254,
0, 258, 0, 2225, 2558, 0, 2353, 0, 1594, 0, 0, 55, 1750, 1394, 3226, 1301,
0, 0, 0, 3427, 0, 1581, 2155, 1640, 3332, 451, 1785, 1132, 2763, 1063, 602, 0,
1463, 0, 1265, 144, 0, 612, 0, 0, 1989, 864, 3802, 211, 555, 0, 0, 972,
0, 0, 2011, 2863, 53, 2944, 2721, 656, 679, 684, 0, 3843, 2270, 0, 0, 0,
232, 0, 0, 646, 2972, 2376, 470, 2015, 14, 1286, 0, 3013, 663, 0, 1309, 511,
485, 322, 968, 0, 3758, 3681, 0, 0, 1197, 3876, 2405, 0, 0, 273, 0, 1596,
0, 658, 448, 1043, 2554, 2343, 1281, 0, 0, 2606, 227, 0, 3498, 1706, 1058, 3796,
0, 3027, 0, 0, 1864, 0, 0, 1728, 3572, 3330, 0, 0, 0, 72, 448, 0,
1811, 0, 1034, 3814, 2837, 0, 0, 1824, 3350, 1820, 2016, 689, 0, 0, 0, 0,
499, 671, 3731, 0, 805, 3522, 447, 745, 456, 3191, 1882, 2298, 0, 103, 339, 822,
3732, 0, 216, 441, 2269, 1743, 1110, 0, 1928, 0, 0, 253, 1576, 211, 1320, 708,
1707, 0, 0, 1743, 3656, 236, 0, 3903, 2046, 2384, 1190, 967, 465, 3326, 1484, 1920,
616, 1986, 2208, 2179, 1626, 589, 1855, 387, 2566, 0, 815, 0, 1424, 3404, 981, 3034,
1949, 0, 351, 0, 0, 0, 0, 2061, 0, 1131, 0, 1541, 1708, 127, 0, 1362,
1251, 3282, 1798, 233, 0, 817, 0, 1076, 463, 2593, 0, 720, 0, 0, 0, 3508,
0, 0, 311, 1139, 2759, 0, 353, 252, 0, 0, 0, 0, 589, 0, 0, 1,
420, 2962, 0, 2529, 2257, 596, 74, 3905, 0, 0, 0, 0, 0, 1916, 0, 3598,
2121, 0, 0, 3874, 0, 1721, 505, 1667, 0, 0, 532, 0, 1076, 951, 684, 2946,
405, 0, 0, 0, 1391, 559, 181, 1624, 0, 0, 0, 0, 496, 2884, 104, 936,
0, 3761, 716, 524, 0, 66, 1686, 0, 1129, 3171, 1401, 2579, 0, 41, 792, 0,
0, 1259, 636, 0, 1740, 1802, 0, 2804, 530, 1137, 678, 1596, 812, 1244, 2113, 0,
0, 0, 0, 0, 2170, 2637, 1089, 26, 0, 3345, 483, 0, 0, 851, 973, 0,
632, 1321, 2012, 3907, 0, 359, 1503, 786, 1268, 601, 1155, 0, 1910, 0, 0, 1693,
0, 583, 321, 0, 0, 1384, 1926, 887, 3904, 594, 1573, 1274, 865, 93, 1800, 837,
256, 397, 1062, 206, 3234, 0, 550, 0, 1456, 0, 2301, 3778, 3141, 2236, 3349, 1651,
1944, 3756, 0, 0, 238, 510, 1889, 2204, 3174, 309, 1593, 0, 3621, 0, 1145, 0,
812, 0, 0, 0, 0, 0, 514, 0, 0, 0, 1692, 1164, 1606, 229, 0, 3901,
0, 1755, 3618, 1592, 2160, 712, 658, 0, 0, 2376, 1427, 555, 0, 319, 0, 0,
1284, 1159, 0, 0, 0, 0, 3297, 1975, 0, 3559, 835, 3885, 0, 2098, 0, 0,
513, 3788, 1223, 1182, 2653, 0, 0, 3437, 0, 117, 0, 1103, 2203, 0, 0, 544,
3482, 560, 741, 0, 869, 3562, 1071, 0, 1407, 0, 1017, 1592, 0, 98, 3137, 0,
1188, 0, 741, 0, 0, 0};
int MangledHashG(const char *key, const int *T)
{
......@@ -304,28 +304,28 @@ constexpr int unmangledkT1[] = {361, 84, 287, 107, 189, 235, 216, 268, 315, 73,
constexpr int unmangledkT2[] = {116, 270, 65, 391, 92, 345, 246, 10, 306, 20, 206, 346, 291,
195, 244, 398, 269, 237, 25, 394, 247, 248, 315, 180, 233, 167};
constexpr int unmangledkG[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 34, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 42, 391, 0, 0, 0, 0, 7, 0, 187, 0, 64, 237,
346, 374, 116, 192, 0, 217, 0, 129, 0, 0, 0, 0, 0, 383, 0, 0, 0, 0, 0,
119, 0, 107, 0, 284, 276, 9, 313, 214, 0, 150, 167, 228, 169, 15, 0, 0, 247, 25,
348, 0, 399, 68, 199, 0, 348, 0, 0, 154, 31, 0, 0, 183, 0, 0, 338, 321, 0,
0, 0, 0, 2, 244, 73, 61, 0, 0, 294, 0, 51, 178, 0, 0, 12, 28, 202, 0,
148, 144, 0, 0, 0, 196, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 274, 0, 232, 56, 0, 315, 358, 0, 0, 0, 306, 21, 353, 0, 0, 0, 0, 0,
42, 0, 325, 21, 8, 272, 0, 0, 123, 401, 0, 85, 40, 305, 0, 0, 0, 0, 0,
0, 0, 7, 204, 56, 142, 405, 0, 0, 0, 335, 161, 0, 195, 0, 109, 206, 57, 40,
0, 0, 278, 17, 0, 148, 0, 163, 88, 0, 0, 0, 125, 0, 118, 0, 0, 0, 257,
285, 0, 16, 0, 191, 0, 0, 12, 0, 339, 71, 323, 21, 99, 0, 0, 187, 0, 22,
167, 271, 0, 258, 0, 0, 0, 17, 30, 0, 0, 0, 181, 218, 0, 0, 109, 0, 209,
154, 332, 54, 256, 0, 0, 0, 319, 14, 152, 82, 50, 0, 0, 15, 218, 0, 0, 0,
0, 120, 0, 218, 162, 0, 47, 229, 219, 0, 86, 117, 313, 197, 98, 0, 0, 0, 0,
124, 1, 204, 86, 0, 0, 0, 377, 0, 8, 75, 0, 0, 391, 106, 374, 0, 197, 0,
353, 179, 293, 0, 3, 70, 0, 164, 7, 0, 0, 136, 0, 247, 193, 0, 52, 319, 248,
0, 357, 109, 0, 77, 0, 0, 0, 227, 143, 81, 101, 0, 217, 0, 0, 0, 37, 0,
172, 0, 0, 0, 14, 175, 0, 53, 361, 0, 131, 191, 304, 43, 0, 0, 198, 0, 86,
0, 336, 0, 0, 0, 335, 277, 0, 386, 360, 8, 135, 87, 30, 281, 0, 0, 0, 11,
262, 389, 301, 233, 36, 190, 150, 0, 0, 0, 325, 0, 388, 0, 155, 33, 382, 6, 4,
0, 165, 126, 218, 369, 0, 0, 17};
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 0, 0, 30, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 46, 388, 0, 0, 0, 0, 3, 0, 189, 0, 60, 239,
349, 372, 117, 196, 0, 219, 0, 133, 0, 0, 0, 0, 0, 385, 0, 0, 0, 0, 0,
118, 0, 105, 0, 277, 279, 9, 316, 221, 0, 147, 168, 224, 170, 11, 0, 0, 249, 25,
345, 0, 399, 64, 203, 0, 349, 0, 0, 155, 31, 0, 0, 182, 0, 0, 335, 319, 0,
0, 0, 0, 2, 240, 73, 61, 0, 0, 296, 0, 51, 179, 0, 0, 12, 28, 207, 0,
149, 149, 0, 0, 0, 197, 12, 404, 0, 0, 0, 0, 0, 0, 0, 0, 404, 0, 0,
0, 273, 0, 230, 60, 0, 320, 354, 0, 0, 0, 305, 21, 348, 0, 0, 0, 0, 0,
42, 0, 328, 21, 12, 271, 0, 0, 122, 395, 0, 65, 44, 304, 0, 0, 0, 0, 0,
0, 0, 13, 203, 56, 146, 405, 0, 0, 0, 338, 160, 0, 192, 0, 108, 204, 58, 40,
0, 0, 276, 17, 0, 145, 0, 164, 88, 0, 0, 0, 126, 0, 116, 0, 0, 0, 253,
280, 0, 16, 0, 192, 0, 0, 319, 0, 344, 71, 322, 21, 102, 0, 0, 182, 0, 22,
168, 274, 0, 254, 0, 0, 0, 37, 34, 0, 0, 0, 182, 213, 0, 0, 110, 0, 209,
171, 333, 54, 257, 0, 0, 0, 324, 14, 149, 82, 50, 0, 0, 15, 215, 0, 0, 0,
0, 119, 0, 222, 163, 0, 48, 228, 217, 0, 89, 116, 311, 198, 97, 0, 0, 0, 0,
123, 1, 205, 86, 0, 0, 0, 381, 0, 4, 75, 0, 0, 391, 104, 376, 0, 195, 0,
351, 180, 292, 0, 0, 70, 0, 165, 10, 0, 0, 137, 0, 248, 190, 0, 52, 318, 252,
0, 360, 112, 0, 77, 0, 0, 0, 228, 142, 85, 102, 0, 221, 0, 0, 0, 37, 0,
173, 0, 0, 0, 14, 176, 0, 53, 364, 0, 132, 193, 302, 43, 0, 0, 199, 0, 83,
0, 332, 0, 0, 0, 332, 280, 0, 406, 356, 8, 136, 93, 30, 280, 0, 0, 0, 11,
260, 386, 304, 236, 32, 191, 151, 0, 0, 0, 324, 0, 391, 0, 156, 33, 383, 6, 4,
0, 166, 127, 222, 373, 0, 0, 14};
int UnmangledHashG(const char *key, const int *T)
{
......
......@@ -244,6 +244,8 @@ enum TOperator : uint16_t
EOpUmulExtended,
EOpImulExtended,
// Group Texture
// Group TextureFirstVersions
EOpTexture2D,
EOpTexture2DProj,
......@@ -256,17 +258,12 @@ enum TOperator : uint16_t
EOpShadow1DProj,
EOpShadow2D,
EOpShadow2DProj,
// Group ARB_texture_rectangle
EOpTexture2DRect,
EOpTexture2DRectProj,
EOpTextureRect,
EOpTextureProjRect,
// Group EXT_shader_texture_lod
EOpTexture2DGradEXT,
EOpTexture2DProjGradEXT,
EOpTextureCubeGradEXT,
EOpTextureVideoWEBGL,
// Group TextureFirstVersionsFS
EOpTexture2DFS,
......@@ -307,7 +304,9 @@ enum TOperator : uint16_t
// Group TextureNoBias
EOpTexture,
EOpTextureRect,
EOpTextureProj,
EOpTextureProjRect,
EOpTextureLod,
EOpTextureSize,
EOpTextureProjLod,
......@@ -337,10 +336,6 @@ enum TOperator : uint16_t
EOpTextureOffsetBias,
EOpTextureProjOffsetBias,
// Group EXT_yuv_target
EOpRgb_2_yuv,
EOpYuv_2_rgb,
// Group TextureGather
EOpTextureGather,
......@@ -360,6 +355,10 @@ enum TOperator : uint16_t
// Group TextureGatherOffsetsComp
EOpTextureGatherOffsetsComp,
// Group EXT_YUV_target
EOpRgb_2_yuv,
EOpYuv_2_rgb,
// Group DerivativesFS
EOpDFdx,
EOpDFdy,
......@@ -453,9 +452,6 @@ enum TOperator : uint16_t
EOpAnyInvocation,
EOpAllInvocations,
EOpAllInvocationsEqual,
// Group WEBGLVideoTexture
EOpTextureVideoWEBGL,
};
// Returns the string corresponding to the operator in GLSL. For built-in functions use the
......@@ -511,6 +507,10 @@ static inline bool IsTextureGather(TOperator op)
{
return op >= EOpTextureGather && op <= EOpTextureGatherOffsetsComp;
}
static inline bool IsTexture(TOperator op)
{
return op >= EOpTexture2D && op <= EOpTextureGatherOffsetsComp;
}
static inline bool IsInterpolationFS(TOperator op)
{
return op >= EOpInterpolateAtCentroid && op <= EOpInterpolateAtOffset;
......
......@@ -224,6 +224,7 @@ class OutputSPIRVTraverser : public TIntermTraverser
spirv::IdRef createConstructorMatrixFromMatrix(TIntermAggregate *node,
spirv::IdRef typeId,
const spirv::IdRefList &parameters);
spirv::IdRefList loadAllParams(TIntermOperator *node);
void extractComponents(TIntermAggregate *node,
size_t componentCount,
const spirv::IdRefList &parameters,
......@@ -232,8 +233,13 @@ class OutputSPIRVTraverser : public TIntermTraverser
void startShortCircuit(TIntermBinary *node);
spirv::IdRef endShortCircuit(TIntermBinary *node, spirv::IdRef *typeId);
spirv::IdRef visitOperator(TIntermOperator *node, spirv::IdRef resultTypeId);
spirv::IdRef createIncrementDecrement(TIntermOperator *node, spirv::IdRef resultTypeId);
spirv::IdRef createAtomicBuiltIn(TIntermOperator *node, spirv::IdRef resultTypeId);
spirv::IdRef createTextureBuiltIn(TIntermOperator *node, spirv::IdRef resultTypeId);
spirv::IdRef createImageBuiltIn(TIntermOperator *node, spirv::IdRef resultTypeId);
spirv::IdRef createFunctionCall(TIntermAggregate *node, spirv::IdRef resultTypeId);
spirv::IdRef createAtomicBuiltIn(TIntermAggregate *node, spirv::IdRef resultTypeId);
ANGLE_MAYBE_UNUSED TCompiler *mCompiler;
ANGLE_MAYBE_UNUSED ShCompileOptions mCompileOptions;
......@@ -903,22 +909,8 @@ spirv::IdRef OutputSPIRVTraverser::createConstructor(TIntermAggregate *node, spi
const TIntermSequence &arguments = *node->getSequence();
const TType &arg0Type = arguments[0]->getAsTyped()->getType();
const size_t parameterCount = node->getChildCount();
spirv::IdRefList parameters;
for (size_t paramIndex = 0; paramIndex < parameterCount; ++paramIndex)
{
// Take each constructor argument that is visited and evaluate it as rvalue
NodeData &param = mNodeData[mNodeData.size() - parameterCount + paramIndex];
const spirv::IdRef paramValue = accessChainLoad(
&param,
mBuilder.getDecorations(node->getChildNode(paramIndex)->getAsTyped()->getType()));
// TODO: handle mismatching types. http://anglebug.com/6000
parameters.push_back(paramValue);
}
// Take each constructor argument that is visited and evaluate it as rvalue
spirv::IdRefList parameters = loadAllParams(node);
// Constructors in GLSL can take various shapes, resulting in different translations to SPIR-V
// (in each case, if the parameter doesn't match the type being constructed, it must be cast):
......@@ -1276,6 +1268,28 @@ spirv::IdRef OutputSPIRVTraverser::createConstructorMatrixFromMatrix(
return result;
}
spirv::IdRefList OutputSPIRVTraverser::loadAllParams(TIntermOperator *node)
{
const size_t parameterCount = node->getChildCount();
spirv::IdRefList parameters;
for (size_t paramIndex = 0; paramIndex < parameterCount; ++paramIndex)
{
// Take each parameter that is visited and evaluate it as rvalue
NodeData &param = mNodeData[mNodeData.size() - parameterCount + paramIndex];
const spirv::IdRef paramValue = accessChainLoad(
&param,
mBuilder.getDecorations(node->getChildNode(paramIndex)->getAsTyped()->getType()));
// TODO: handle mismatching types. http://anglebug.com/6000
parameters.push_back(paramValue);
}
return parameters;
}
void OutputSPIRVTraverser::extractComponents(TIntermAggregate *node,
size_t componentCount,
const spirv::IdRefList &parameters,
......@@ -1545,392 +1559,120 @@ spirv::IdRef OutputSPIRVTraverser::createFunctionCall(TIntermAggregate *node,
return result;
}
spirv::IdRef OutputSPIRVTraverser::createAtomicBuiltIn(TIntermAggregate *node,
spirv::IdRef resultTypeId)
bool IsShortCircuitNeeded(TIntermOperator *node)
{
// Most atomic instructions are in the form of:
//
// %result = OpAtomicX %pointer Scope MemorySemantics %value
//
// OpAtomicCompareSwap is exceptionally different (note that compare and value are in different
// order than in GLSL):
//
// %result = OpAtomicCompareExchange %pointer
// Scope MemorySemantics MemorySemantics
// %value %comparator
//
// TODO: Turn image atomic functions into ops. Saves generating many built-in variations, and
// lets this function handle both. http://anglebug.com/4889
// In all cases, the first parameter is the pointer, and the rest are rvalues.
const size_t parameterCount = node->getChildCount();
spirv::IdRef pointerId;
spirv::IdRefList parameters;
ASSERT(parameterCount >= 2);
pointerId = accessChainCollapse(&mNodeData[mNodeData.size() - parameterCount]);
for (size_t paramIndex = 1; paramIndex < parameterCount; ++paramIndex)
{
NodeData &param = mNodeData[mNodeData.size() - parameterCount + paramIndex];
parameters.push_back(accessChainLoad(
&param,
mBuilder.getDecorations(node->getChildNode(paramIndex)->getAsTyped()->getType())));
}
// The scope of the operation is always Device as we don't enable the Vulkan memory model
// extension.
const spirv::IdScope scopeId = mBuilder.getUintConstant(spv::ScopeDevice);
// The memory semantics is always relaxed as we don't enable the Vulkan memory model extension.
const spirv::IdMemorySemantics semanticsId =
mBuilder.getUintConstant(spv::MemorySemanticsMaskNone);
using WriteAtomicOp =
void (*)(spirv::Blob * blob, spirv::IdResultType idResultType, spirv::IdResult idResult,
spirv::IdRef pointer, spirv::IdScope scope, spirv::IdMemorySemantics semantics,
spirv::IdRef value);
WriteAtomicOp writeAtomicOp = nullptr;
const spirv::IdRef result = mBuilder.getNewId(mBuilder.getDecorations(node->getType()));
const bool isUnsigned =
node->getChildNode(0)->getAsTyped()->getType().getBasicType() == EbtUInt;
TOperator op = node->getOp();
switch (node->getOp())
// Short circuit is only necessary for && and ||.
if (op != EOpLogicalAnd && op != EOpLogicalOr)
{
case EOpAtomicAdd:
writeAtomicOp = spirv::WriteAtomicIAdd;
break;
case EOpAtomicMin:
writeAtomicOp = isUnsigned ? spirv::WriteAtomicUMin : spirv::WriteAtomicSMin;
break;
case EOpAtomicMax:
writeAtomicOp = isUnsigned ? spirv::WriteAtomicUMax : spirv::WriteAtomicSMax;
break;
case EOpAtomicAnd:
writeAtomicOp = spirv::WriteAtomicAnd;
break;
case EOpAtomicOr:
writeAtomicOp = spirv::WriteAtomicOr;
break;
case EOpAtomicXor:
writeAtomicOp = spirv::WriteAtomicXor;
break;
case EOpAtomicExchange:
writeAtomicOp = spirv::WriteAtomicExchange;
break;
case EOpAtomicCompSwap:
// Generate this special instruction right here and early out. Note again that the
// value and compare parameters of OpAtomicCompareExchange are in the opposite order
// from GLSL.
ASSERT(parameters.size() == 2);
spirv::WriteAtomicCompareExchange(mBuilder.getSpirvCurrentFunctionBlock(), resultTypeId,
result, pointerId, scopeId, semanticsId, semanticsId,
parameters[1], parameters[0]);
return result;
default:
UNREACHABLE();
return false;
}
// Write the instruction.
ASSERT(parameters.size() == 1);
writeAtomicOp(mBuilder.getSpirvCurrentFunctionBlock(), resultTypeId, result, pointerId, scopeId,
semanticsId, parameters[0]);
ASSERT(node->getChildCount() == 2);
return result;
// If the right hand side does not have side effects, short-circuiting is unnecessary.
// TODO: experiment with the performance of OpLogicalAnd/Or vs short-circuit based on the
// complexity of the right hand side expression. We could potentially only allow
// OpLogicalAnd/Or if the right hand side is a constant or an access chain and have more complex
// expressions be placed inside an if block. http://anglebug.com/4889
return node->getChildNode(1)->getAsTyped()->hasSideEffects();
}
void OutputSPIRVTraverser::visitSymbol(TIntermSymbol *node)
using WriteUnaryOp = void (*)(spirv::Blob *blob,
spirv::IdResultType idResultType,
spirv::IdResult idResult,
spirv::IdRef operand);
using WriteBinaryOp = void (*)(spirv::Blob *blob,
spirv::IdResultType idResultType,
spirv::IdResult idResult,
spirv::IdRef operand1,
spirv::IdRef operand2);
using WriteTernaryOp = void (*)(spirv::Blob *blob,
spirv::IdResultType idResultType,
spirv::IdResult idResult,
spirv::IdRef operand1,
spirv::IdRef operand2,
spirv::IdRef operand3);
using WriteQuaternaryOp = void (*)(spirv::Blob *blob,
spirv::IdResultType idResultType,
spirv::IdResult idResult,
spirv::IdRef operand1,
spirv::IdRef operand2,
spirv::IdRef operand3,
spirv::IdRef operand4);
using WriteAtomicOp = void (*)(spirv::Blob *blob,
spirv::IdResultType idResultType,
spirv::IdResult idResult,
spirv::IdRef pointer,
spirv::IdScope scope,
spirv::IdMemorySemantics semantics,
spirv::IdRef value);
spirv::IdRef OutputSPIRVTraverser::visitOperator(TIntermOperator *node, spirv::IdRef resultTypeId)
{
// Constants are expected to be folded.
ASSERT(!node->hasConstantValue());
// No-op visits to symbols that are being declared. They are handled in visitDeclaration.
if (mIsSymbolBeingDeclared)
// Handle special groups.
const TOperator op = node->getOp();
if (op == EOpPostIncrement || op == EOpPreIncrement || op == EOpPostDecrement ||
op == EOpPreDecrement)
{
// Make sure this does not affect other symbols, for example in the initializer expression.
mIsSymbolBeingDeclared = false;
return;
return createIncrementDecrement(node, resultTypeId);
}
mNodeData.emplace_back();
// The symbol is either:
//
// - A specialization constant
// - A variable (local, varying etc)
// - An interface block
// - A field of an unnamed interface block
//
// Specialization constants in SPIR-V are treated largely like constants, in which case make
// this behave like visitConstantUnion().
const TType &type = node->getType();
const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();
const TSymbol *symbol = interfaceBlock;
if (interfaceBlock == nullptr)
if (BuiltInGroup::IsAtomicMemory(op) || BuiltInGroup::IsImageAtomic(op))
{
symbol = &node->variable();
return createAtomicBuiltIn(node, resultTypeId);
}
// Track the block storage; it's needed to determine the derived type in an access chain, but is
// not promoted in intermediate nodes' TType.
TLayoutBlockStorage blockStorage = EbsUnspecified;
if (interfaceBlock)
if (BuiltInGroup::IsTexture(op))
{
blockStorage = mBuilder.getBlockStorage(type);
return createTextureBuiltIn(node, resultTypeId);
}
const spirv::IdRef typeId = mBuilder.getTypeData(type, blockStorage).id;
// If the symbol is a const variable, such as a const function parameter or specialization
// constant, create an rvalue.
if (type.getQualifier() == EvqConst || type.getQualifier() == EvqSpecConst)
if (BuiltInGroup::IsImage(op))
{
ASSERT(mSymbolIdMap.count(symbol) > 0);
nodeDataInitRValue(&mNodeData.back(), mSymbolIdMap[symbol], typeId);
return;
return createImageBuiltIn(node, resultTypeId);
}
// Otherwise create an lvalue.
spv::StorageClass storageClass;
const spirv::IdRef symbolId = getSymbolIdAndStorageClass(symbol, type, &storageClass);
nodeDataInitLValue(&mNodeData.back(), symbolId, typeId, storageClass, blockStorage);
// If a field of a nameless interface block, create an access chain.
if (interfaceBlock && !type.isInterfaceBlock())
{
uint32_t fieldIndex = static_cast<uint32_t>(type.getInterfaceBlockFieldIndex());
accessChainPushLiteral(&mNodeData.back(), spirv::LiteralInteger(fieldIndex), typeId);
}
}
const size_t childCount = node->getChildCount();
TIntermTyped *firstChild = node->getChildNode(0)->getAsTyped();
void OutputSPIRVTraverser::visitConstantUnion(TIntermConstantUnion *node)
{
mNodeData.emplace_back();
const TType &firstOperandType = firstChild->getType();
const TBasicType basicType = firstOperandType.getBasicType();
const bool isFloat = basicType == EbtFloat || basicType == EbtDouble;
const bool isUnsigned = basicType == EbtUInt;
const bool isBool = basicType == EbtBool;
const bool operateOnColumns = firstOperandType.isMatrix();
// Whether the operands need to be swapped in the (binary) instruction
bool binarySwapOperands = false;
// Whether the scalar operand needs to be extended to match the other operand which is a vector
// (in a binary operation).
bool binaryExtendScalarToVector = true;
const TType &type = node->getType();
WriteUnaryOp writeUnaryOp = nullptr;
WriteBinaryOp writeBinaryOp = nullptr;
WriteTernaryOp writeTernaryOp = nullptr;
WriteQuaternaryOp writeQuaternaryOp = nullptr;
// Find out the expected type for this constant, so it can be cast right away and not need an
// instruction to do that.
TIntermNode *parent = getParentNode();
const size_t childIndex = getParentChildIndex(PreVisit);
// Some operators are implemented with an extended instruction.
spv::GLSLstd450 extendedInst = spv::GLSLstd450Bad;
TBasicType expectedBasicType = type.getBasicType();
if (parent->getAsAggregate())
switch (op)
{
TIntermAggregate *parentAggregate = parent->getAsAggregate();
// There are three possibilities:
//
// - It's a struct constructor: The basic type must match that of the corresponding field of
// the struct.
// - It's a non struct constructor: The basic type must match that of the the type being
// constructed.
// - It's a function call: The basic type must match that of the corresponding argument.
if (parentAggregate->isConstructor())
{
const TStructure *structure = parentAggregate->getType().getStruct();
if (structure != nullptr)
{
expectedBasicType = structure->fields()[childIndex]->type()->getBasicType();
}
case EOpNegative:
if (isFloat)
writeUnaryOp = spirv::WriteFNegate;
else
{
expectedBasicType = parentAggregate->getType().getBasicType();
}
}
else
{
expectedBasicType =
parentAggregate->getFunction()->getParam(childIndex)->getType().getBasicType();
}
}
// TODO: other node types such as binary, ternary etc. http://anglebug.com/4889
const spirv::IdRef typeId = mBuilder.getTypeData(type, EbsUnspecified).id;
const spirv::IdRef constId = createConstant(type, expectedBasicType, node->getConstantValue());
nodeDataInitRValue(&mNodeData.back(), constId, typeId);
}
bool OutputSPIRVTraverser::visitSwizzle(Visit visit, TIntermSwizzle *node)
{
// Constants are expected to be folded.
ASSERT(!node->hasConstantValue());
if (visit == PreVisit)
{
// Don't add an entry to the stack. The child will create one, which we won't pop.
return true;
}
ASSERT(visit == PostVisit);
ASSERT(mNodeData.size() >= 1);
writeUnaryOp = spirv::WriteSNegate;
break;
case EOpPositive:
// This is a noop.
return accessChainLoad(&mNodeData.back(), mBuilder.getDecorations(firstOperandType));
const TType &vectorType = node->getOperand()->getType();
const uint8_t vectorComponentCount = static_cast<uint8_t>(vectorType.getNominalSize());
const TVector<int> &swizzle = node->getSwizzleOffsets();
// As an optimization, do nothing if the swizzle is selecting all the components of the vector
// in order.
bool isIdentity = swizzle.size() == vectorComponentCount;
for (size_t index = 0; index < swizzle.size(); ++index)
{
isIdentity = isIdentity && static_cast<size_t>(swizzle[index]) == index;
}
if (isIdentity)
{
return true;
}
const spirv::IdRef typeId =
mBuilder.getTypeData(node->getType(), mNodeData.back().accessChain.baseBlockStorage).id;
accessChainPushSwizzle(&mNodeData.back(), swizzle, typeId, vectorComponentCount);
return true;
}
bool IsShortCircuitNeeded(TIntermBinary *node)
{
TOperator op = node->getOp();
// Short circuit is only necessary for && and ||.
if (op != EOpLogicalAnd && op != EOpLogicalOr)
{
return false;
}
// If the right hand side does not have side effects, short-circuiting is unnecessary.
// TODO: experiment with the performance of OpLogicalAnd/Or vs short-circuit based on the
// complexity of the right hand side expression. We could potentially only allow
// OpLogicalAnd/Or if the right hand side is a constant or an access chain and have more complex
// expressions be placed inside an if block. http://anglebug.com/4889
return node->getRight()->hasSideEffects();
}
bool OutputSPIRVTraverser::visitBinary(Visit visit, TIntermBinary *node)
{
// Constants are expected to be folded.
ASSERT(!node->hasConstantValue());
if (visit == PreVisit)
{
// Don't add an entry to the stack. The left child will create one, which we won't pop.
return true;
}
// If this is a variable initialization node, defer any code generation to visitDeclaration.
if (node->getOp() == EOpInitialize)
{
ASSERT(getParentNode()->getAsDeclarationNode() != nullptr);
return true;
}
if (IsShortCircuitNeeded(node))
{
// For && and ||, if short-circuiting behavior is needed, we need to emulate it with an
// |if| construct. At this point, the left-hand side is already evaluated, so we need to
// create an appropriate conditional on in-visit and visit the right-hand-side inside the
// conditional block. On post-visit, OpPhi is used to calculate the result.
if (visit == InVisit)
{
startShortCircuit(node);
return true;
}
spirv::IdRef typeId;
const spirv::IdRef result = endShortCircuit(node, &typeId);
// Replace the access chain with an rvalue that's the result.
nodeDataInitRValue(&mNodeData.back(), result, typeId);
return true;
}
if (visit == InVisit)
{
// Left child visited. Take the entry it created as the current node's.
ASSERT(mNodeData.size() >= 1);
// As an optimization, if the index is EOpIndexDirect*, take the constant index directly and
// add it to the access chain as literal.
switch (node->getOp())
{
case EOpIndexDirect:
case EOpIndexDirectStruct:
case EOpIndexDirectInterfaceBlock:
accessChainPushLiteral(
&mNodeData.back(),
spirv::LiteralInteger(node->getRight()->getAsConstantUnion()->getIConst(0)),
mBuilder
.getTypeData(node->getType(), mNodeData.back().accessChain.baseBlockStorage)
.id);
// Don't visit the right child, it's already processed.
return false;
default:
break;
}
return true;
}
// There are at least two entries, one for the left node and one for the right one.
ASSERT(mNodeData.size() >= 2);
// Load the result of the right node right away.
spirv::IdRef typeId = getAccessChainTypeId(&mNodeData.back());
spirv::IdRef rightValue =
accessChainLoad(&mNodeData.back(), mBuilder.getDecorations(node->getRight()->getType()));
mNodeData.pop_back();
// For EOpIndex* operations, push the right value as an index to the left value's access chain.
// For the other operations, evaluate the expression.
NodeData &left = mNodeData.back();
const TBasicType leftBasicType = node->getLeft()->getType().getBasicType();
const bool isFloat = leftBasicType == EbtFloat || leftBasicType == EbtDouble;
const bool isUnsigned = leftBasicType == EbtUInt;
const bool isBool = leftBasicType == EbtBool;
// Whether the operands need to be swapped in the instruction
bool swapOperands = false;
// Whether the scalar operand needs to be extended to match the other operand which is a vector.
bool extendScalarToVector = true;
using WriteBinaryOp =
void (*)(spirv::Blob * blob, spirv::IdResultType idResultType, spirv::IdResult idResult,
spirv::IdRef operand1, spirv::IdRef operand2);
WriteBinaryOp writeBinaryOp = nullptr;
switch (node->getOp())
{
case EOpIndexDirect:
case EOpIndexDirectStruct:
case EOpIndexDirectInterfaceBlock:
UNREACHABLE();
return true;
case EOpIndexIndirect:
typeId = mBuilder.getTypeData(node->getType(), left.accessChain.baseBlockStorage).id;
if (!node->getLeft()->getType().isArray() && node->getLeft()->getType().isVector())
{
accessChainPushDynamicComponent(&left, rightValue, typeId);
}
else
{
accessChainPush(&left, rightValue, typeId);
}
return true;
case EOpAssign:
// Store into the access chain. Since the result of the (a = b) expression is b, change
// the access chain to an unindexed rvalue which is |rightValue|.
accessChainStore(&left, rightValue);
nodeDataInitRValue(&left, rightValue, typeId);
return true;
case EOpLogicalNot:
case EOpNotComponentWise:
writeUnaryOp = spirv::WriteLogicalNot;
break;
case EOpBitwiseNot:
writeUnaryOp = spirv::WriteNot;
break;
case EOpAdd:
case EOpAddAssign:
......@@ -1948,6 +1690,7 @@ bool OutputSPIRVTraverser::visitBinary(Visit visit, TIntermBinary *node)
break;
case EOpMul:
case EOpMulAssign:
case EOpMatrixCompMult:
if (isFloat)
writeBinaryOp = spirv::WriteFMul;
else
......@@ -1972,33 +1715,6 @@ bool OutputSPIRVTraverser::visitBinary(Visit visit, TIntermBinary *node)
writeBinaryOp = spirv::WriteSMod;
break;
case EOpVectorTimesScalar:
case EOpVectorTimesScalarAssign:
if (isFloat)
{
writeBinaryOp = spirv::WriteVectorTimesScalar;
swapOperands = node->getRight()->getType().isVector();
extendScalarToVector = false;
}
else
writeBinaryOp = spirv::WriteIMul;
break;
case EOpVectorTimesMatrix:
case EOpVectorTimesMatrixAssign:
writeBinaryOp = spirv::WriteVectorTimesMatrix;
break;
case EOpMatrixTimesVector:
writeBinaryOp = spirv::WriteMatrixTimesVector;
break;
case EOpMatrixTimesScalar:
case EOpMatrixTimesScalarAssign:
writeBinaryOp = spirv::WriteMatrixTimesScalar;
break;
case EOpMatrixTimesMatrix:
case EOpMatrixTimesMatrixAssign:
writeBinaryOp = spirv::WriteMatrixTimesMatrix;
break;
case EOpEqual:
case EOpEqualComponentWise:
if (isFloat)
......@@ -2054,19 +1770,46 @@ bool OutputSPIRVTraverser::visitBinary(Visit visit, TIntermBinary *node)
writeBinaryOp = spirv::WriteSGreaterThanEqual;
break;
case EOpVectorTimesScalar:
case EOpVectorTimesScalarAssign:
if (isFloat)
{
writeBinaryOp = spirv::WriteVectorTimesScalar;
binarySwapOperands = node->getChildNode(1)->getAsTyped()->getType().isVector();
binaryExtendScalarToVector = false;
}
else
writeBinaryOp = spirv::WriteIMul;
break;
case EOpVectorTimesMatrix:
case EOpVectorTimesMatrixAssign:
writeBinaryOp = spirv::WriteVectorTimesMatrix;
break;
case EOpMatrixTimesVector:
writeBinaryOp = spirv::WriteMatrixTimesVector;
break;
case EOpMatrixTimesScalar:
case EOpMatrixTimesScalarAssign:
writeBinaryOp = spirv::WriteMatrixTimesScalar;
break;
case EOpMatrixTimesMatrix:
case EOpMatrixTimesMatrixAssign:
writeBinaryOp = spirv::WriteMatrixTimesMatrix;
break;
case EOpLogicalOr:
ASSERT(!IsShortCircuitNeeded(node));
extendScalarToVector = false;
writeBinaryOp = spirv::WriteLogicalOr;
binaryExtendScalarToVector = false;
writeBinaryOp = spirv::WriteLogicalOr;
break;
case EOpLogicalXor:
extendScalarToVector = false;
writeBinaryOp = spirv::WriteLogicalNotEqual;
binaryExtendScalarToVector = false;
writeBinaryOp = spirv::WriteLogicalNotEqual;
break;
case EOpLogicalAnd:
ASSERT(!IsShortCircuitNeeded(node));
extendScalarToVector = false;
writeBinaryOp = spirv::WriteLogicalAnd;
binaryExtendScalarToVector = false;
writeBinaryOp = spirv::WriteLogicalAnd;
break;
case EOpBitShiftLeft:
......@@ -2093,242 +1836,70 @@ bool OutputSPIRVTraverser::visitBinary(Visit visit, TIntermBinary *node)
writeBinaryOp = spirv::WriteBitwiseOr;
break;
default:
UNIMPLEMENTED();
case EOpRadians:
extendedInst = spv::GLSLstd450Radians;
break;
case EOpDegrees:
extendedInst = spv::GLSLstd450Degrees;
break;
case EOpSin:
extendedInst = spv::GLSLstd450Sin;
break;
case EOpCos:
extendedInst = spv::GLSLstd450Cos;
break;
case EOpTan:
extendedInst = spv::GLSLstd450Tan;
break;
case EOpAsin:
extendedInst = spv::GLSLstd450Asin;
break;
case EOpAcos:
extendedInst = spv::GLSLstd450Acos;
break;
case EOpAtan:
extendedInst = spv::GLSLstd450Atan;
break;
case EOpSinh:
extendedInst = spv::GLSLstd450Sinh;
break;
case EOpCosh:
extendedInst = spv::GLSLstd450Cosh;
break;
case EOpTanh:
extendedInst = spv::GLSLstd450Tanh;
break;
case EOpAsinh:
extendedInst = spv::GLSLstd450Asinh;
break;
case EOpAcosh:
extendedInst = spv::GLSLstd450Acosh;
break;
case EOpAtanh:
extendedInst = spv::GLSLstd450Atanh;
break;
}
if (writeBinaryOp)
{
// Load the left value.
spirv::IdRef leftValue =
accessChainLoad(&left, mBuilder.getDecorations(node->getLeft()->getType()));
typeId = mBuilder.getTypeData(node->getType(), EbsUnspecified).id;
// For vector<op>scalar operations that require it, turn the scalar into a vector of the
// same size.
if (extendScalarToVector)
{
const TType &leftType = node->getLeft()->getType();
const TType &rightType = node->getRight()->getType();
if (leftType.isScalar() && rightType.isVector())
{
leftValue = createConstructorVectorFromScalar(rightType, typeId, {{leftValue}});
}
else if (rightType.isScalar() && leftType.isVector())
{
rightValue = createConstructorVectorFromScalar(leftType, typeId, {{rightValue}});
}
}
if (swapOperands)
{
std::swap(leftValue, rightValue);
}
// Write the operation that combines the left and right values.
spirv::IdRef result = mBuilder.getNewId(mBuilder.getDecorations(node->getType()));
writeBinaryOp(mBuilder.getSpirvCurrentFunctionBlock(), typeId, result, leftValue,
rightValue);
// If it's an assignment, store the calculated value.
if (IsAssignment(node->getOp()))
{
accessChainStore(&left, result);
}
// Replace the access chain with an rvalue that's the result.
nodeDataInitRValue(&left, result, typeId);
// TODO: Handle NoContraction decoration. http://anglebug.com/4889
}
return true;
}
bool OutputSPIRVTraverser::visitUnary(Visit visit, TIntermUnary *node)
{
// Constants are expected to be folded.
ASSERT(!node->hasConstantValue());
if (visit == PreVisit)
{
// Don't add an entry to the stack. The child will create one, which we won't pop.
return true;
}
// It's a unary operation, so there can't be an InVisit.
ASSERT(visit != InVisit);
// There is at least on entry for the child.
ASSERT(mNodeData.size() >= 1);
TIntermTyped *operand = node->getOperand();
// Special case EOpArrayLength. .length() on sized arrays is already constant folded, so this
// operation only applies to ssbo.last_member.length(). OpArrayLength takes the ssbo block
// *type* and the field index of last_member, so those need to be extracted from the access
// chain. Additionally, OpArrayLength produces an unsigned int while GLSL produces an int, so a
// final cast is necessary.
if (node->getOp() == EOpArrayLength)
{
// The access chain must only include the base ssbo + one literal field index.
ASSERT(mNodeData.back().idList.size() == 1 && !mNodeData.back().idList.back().id.valid());
const spirv::LiteralInteger fieldIndex = mNodeData.back().idList.back().literal;
// Get the interface block type from the operand, which is either a symbol or a binary
// operator based on whether the interface block is nameless or not.
TIntermTyped *ssbo =
operand->getAsBinaryNode() ? operand->getAsBinaryNode()->getLeft() : operand;
const spirv::IdRef typeId = mBuilder.getTypeData(ssbo->getType(), EbsUnspecified).id;
// Get the int and uint type ids.
SpirvType intType;
intType.type = EbtInt;
const spirv::IdRef intTypeId = mBuilder.getSpirvTypeData(intType, nullptr).id;
intType.type = EbtUInt;
const spirv::IdRef uintTypeId = mBuilder.getSpirvTypeData(intType, nullptr).id;
// Generate the instruction.
const spirv::IdRef resultId = mBuilder.getNewId({});
spirv::WriteArrayLength(mBuilder.getSpirvCurrentFunctionBlock(), uintTypeId, resultId,
typeId, fieldIndex);
// Cast to int.
const spirv::IdRef castResultId = mBuilder.getNewId({});
spirv::WriteBitcast(mBuilder.getSpirvCurrentFunctionBlock(), intTypeId, castResultId,
resultId);
// Replace the access chain with an rvalue that's the result.
nodeDataInitRValue(&mNodeData.back(), castResultId, intTypeId);
return true;
}
// Load the result of the node right away.
spirv::IdRef typeId = getAccessChainTypeId(&mNodeData.back());
spirv::IdRef value =
accessChainLoad(&mNodeData.back(), mBuilder.getDecorations(operand->getType()));
const TType &operandType = operand->getType();
const TBasicType basicType = operandType.getBasicType();
const bool isFloat = basicType == EbtFloat || basicType == EbtDouble;
const bool isUnsigned = basicType == EbtUInt;
const bool operateOnColumns = operandType.isMatrix();
// Some operators are implemented with a unary SPIR-V op.
using WriteUnaryOp = void (*)(spirv::Blob * blob, spirv::IdResultType idResultType,
spirv::IdResult idResult, spirv::IdRef operand);
WriteUnaryOp writeUnaryOp = nullptr;
// Some operators are implemented with a binary SPIR-V op.
using WriteBinaryOp =
void (*)(spirv::Blob * blob, spirv::IdResultType idResultType, spirv::IdResult idResult,
spirv::IdRef operand1, spirv::IdRef operand2);
WriteBinaryOp writeBinaryOp = nullptr;
// Some operators are implemented with an extended instruction.
spv::GLSLstd450 extendedInst = spv::GLSLstd450Bad;
switch (node->getOp())
{
case EOpNegative:
if (isFloat)
writeUnaryOp = spirv::WriteFNegate;
else
writeUnaryOp = spirv::WriteSNegate;
break;
case EOpPositive:
// This is a noop.
break;
case EOpLogicalNot:
case EOpNotComponentWise:
writeUnaryOp = spirv::WriteLogicalNot;
break;
case EOpBitwiseNot:
writeUnaryOp = spirv::WriteNot;
break;
case EOpPostIncrement:
case EOpPreIncrement:
if (isFloat)
writeBinaryOp = spirv::WriteFAdd;
else
writeBinaryOp = spirv::WriteIAdd;
break;
case EOpPostDecrement:
case EOpPreDecrement:
if (isFloat)
writeBinaryOp = spirv::WriteFSub;
else
writeBinaryOp = spirv::WriteISub;
break;
case EOpRadians:
extendedInst = spv::GLSLstd450Radians;
break;
case EOpDegrees:
extendedInst = spv::GLSLstd450Degrees;
break;
case EOpSin:
extendedInst = spv::GLSLstd450Sin;
break;
case EOpCos:
extendedInst = spv::GLSLstd450Cos;
break;
case EOpTan:
extendedInst = spv::GLSLstd450Tan;
break;
case EOpAsin:
extendedInst = spv::GLSLstd450Asin;
break;
case EOpAcos:
extendedInst = spv::GLSLstd450Acos;
break;
break;
case EOpAtan:
extendedInst = spv::GLSLstd450Atan;
break;
case EOpSinh:
extendedInst = spv::GLSLstd450Sinh;
break;
case EOpCosh:
extendedInst = spv::GLSLstd450Cosh;
break;
case EOpTanh:
extendedInst = spv::GLSLstd450Tanh;
break;
case EOpAsinh:
extendedInst = spv::GLSLstd450Asinh;
break;
case EOpAcosh:
extendedInst = spv::GLSLstd450Acosh;
break;
case EOpAtanh:
extendedInst = spv::GLSLstd450Atanh;
break;
case EOpExp:
extendedInst = spv::GLSLstd450Exp;
break;
case EOpLog:
extendedInst = spv::GLSLstd450Log;
break;
case EOpExp2:
extendedInst = spv::GLSLstd450Exp2;
break;
case EOpLog2:
extendedInst = spv::GLSLstd450Log2;
break;
case EOpSqrt:
extendedInst = spv::GLSLstd450Sqrt;
break;
case EOpInversesqrt:
extendedInst = spv::GLSLstd450InverseSqrt;
break;
case EOpPow:
extendedInst = spv::GLSLstd450Pow;
break;
case EOpExp:
extendedInst = spv::GLSLstd450Exp;
break;
case EOpLog:
extendedInst = spv::GLSLstd450Log;
break;
case EOpExp2:
extendedInst = spv::GLSLstd450Exp2;
break;
case EOpLog2:
extendedInst = spv::GLSLstd450Log2;
break;
case EOpSqrt:
extendedInst = spv::GLSLstd450Sqrt;
break;
case EOpInversesqrt:
extendedInst = spv::GLSLstd450InverseSqrt;
break;
case EOpAbs:
if (isFloat)
......@@ -2360,20 +1931,82 @@ bool OutputSPIRVTraverser::visitUnary(Visit visit, TIntermUnary *node)
case EOpFract:
extendedInst = spv::GLSLstd450Fract;
break;
case EOpMod:
if (isFloat)
writeBinaryOp = spirv::WriteFMod;
else if (isUnsigned)
writeBinaryOp = spirv::WriteUMod;
else
writeBinaryOp = spirv::WriteSMod;
break;
case EOpMin:
if (isFloat)
extendedInst = spv::GLSLstd450FMin;
else if (isUnsigned)
extendedInst = spv::GLSLstd450UMin;
else
extendedInst = spv::GLSLstd450SMin;
break;
case EOpMax:
if (isFloat)
extendedInst = spv::GLSLstd450FMax;
else if (isUnsigned)
extendedInst = spv::GLSLstd450UMax;
else
extendedInst = spv::GLSLstd450SMax;
break;
case EOpClamp:
if (isFloat)
extendedInst = spv::GLSLstd450FClamp;
else if (isUnsigned)
extendedInst = spv::GLSLstd450UClamp;
else
extendedInst = spv::GLSLstd450SClamp;
break;
case EOpMix:
if (node->getChildNode(childCount - 1)->getAsTyped()->getType().getBasicType() ==
EbtBool)
{
writeTernaryOp = spirv::WriteSelect;
}
else
{
ASSERT(isFloat);
extendedInst = spv::GLSLstd450FMix;
}
break;
case EOpStep:
extendedInst = spv::GLSLstd450Step;
break;
case EOpSmoothstep:
extendedInst = spv::GLSLstd450SmoothStep;
break;
case EOpModf:
// TODO: modf has an out parameter. http://anglebug.com/4889.
UNIMPLEMENTED();
break;
case EOpIsnan:
writeUnaryOp = spirv::WriteIsNan;
break;
case EOpIsinf:
writeUnaryOp = spirv::WriteIsInf;
break;
case EOpFloatBitsToInt:
case EOpFloatBitsToUint:
case EOpIntBitsToFloat:
case EOpUintBitsToFloat:
writeUnaryOp = spirv::WriteBitcast;
break;
case EOpFma:
extendedInst = spv::GLSLstd450Fma;
break;
case EOpFrexp:
// TODO: frexp has an out parameter. http://anglebug.com/4889.
UNIMPLEMENTED();
break;
case EOpLdexp:
extendedInst = spv::GLSLstd450Ldexp;
break;
case EOpPackSnorm2x16:
extendedInst = spv::GLSLstd450PackSnorm2x16;
break;
......@@ -2392,139 +2025,848 @@ bool OutputSPIRVTraverser::visitUnary(Visit visit, TIntermUnary *node)
case EOpUnpackHalf2x16:
extendedInst = spv::GLSLstd450UnpackHalf2x16;
break;
case EOpPackUnorm4x8:
extendedInst = spv::GLSLstd450PackUnorm4x8;
break;
case EOpPackSnorm4x8:
extendedInst = spv::GLSLstd450PackSnorm4x8;
break;
case EOpUnpackUnorm4x8:
extendedInst = spv::GLSLstd450UnpackUnorm4x8;
break;
case EOpUnpackSnorm4x8:
extendedInst = spv::GLSLstd450UnpackSnorm4x8;
break;
case EOpPackDouble2x32:
case EOpUnpackDouble2x32:
// TODO: support desktop GLSL. http://anglebug.com/4889
UNIMPLEMENTED();
break;
case EOpLength:
extendedInst = spv::GLSLstd450Length;
break;
case EOpDistance:
extendedInst = spv::GLSLstd450Distance;
break;
case EOpDot:
// Use normal multiplication for scalars.
if (firstOperandType.isScalar())
{
if (isFloat)
writeBinaryOp = spirv::WriteFMul;
else
writeBinaryOp = spirv::WriteIMul;
}
else
{
writeBinaryOp = spirv::WriteDot;
}
break;
case EOpCross:
extendedInst = spv::GLSLstd450Cross;
break;
case EOpNormalize:
extendedInst = spv::GLSLstd450Normalize;
break;
case EOpFaceforward:
extendedInst = spv::GLSLstd450FaceForward;
break;
case EOpReflect:
extendedInst = spv::GLSLstd450Reflect;
break;
case EOpRefract:
extendedInst = spv::GLSLstd450Refract;
break;
case EOpFtransform:
// TODO: support desktop GLSL. http://anglebug.com/4889
UNIMPLEMENTED();
break;
case EOpOuterProduct:
writeBinaryOp = spirv::WriteOuterProduct;
break;
case EOpTranspose:
writeUnaryOp = spirv::WriteTranspose;
break;
case EOpDeterminant:
extendedInst = spv::GLSLstd450Determinant;
break;
case EOpInverse:
extendedInst = spv::GLSLstd450MatrixInverse;
break;
case EOpAny:
writeUnaryOp = spirv::WriteAny;
break;
case EOpAll:
writeUnaryOp = spirv::WriteAll;
break;
case EOpBitfieldExtract:
if (isUnsigned)
writeTernaryOp = spirv::WriteBitFieldUExtract;
else
writeTernaryOp = spirv::WriteBitFieldSExtract;
break;
case EOpBitfieldInsert:
writeQuaternaryOp = spirv::WriteBitFieldInsert;
break;
case EOpBitfieldReverse:
writeUnaryOp = spirv::WriteBitReverse;
break;
case EOpBitCount:
writeUnaryOp = spirv::WriteBitCount;
break;
case EOpFindLSB:
extendedInst = spv::GLSLstd450FindILsb;
break;
case EOpFindMSB:
if (isUnsigned)
extendedInst = spv::GLSLstd450FindUMsb;
else
extendedInst = spv::GLSLstd450FindSMsb;
break;
case EOpUaddCarry:
// TODO: uaddCarry has an out parameter. http://anglebug.com/4889.
UNIMPLEMENTED();
break;
case EOpUsubBorrow:
// TODO: usubBorrow has an out parameter. http://anglebug.com/4889.
UNIMPLEMENTED();
break;
case EOpUmulExtended:
// TODO: umulExtended has an out parameter. http://anglebug.com/4889.
UNIMPLEMENTED();
break;
case EOpImulExtended:
// TODO: imulExtended has an out parameter. http://anglebug.com/4889.
UNIMPLEMENTED();
break;
case EOpRgb_2_yuv:
case EOpYuv_2_rgb:
// TODO: There doesn't seem to be an equivalent in SPIR-V, and should likley be emulated
// as an AST transformation. Not supported by the Vulkan at the moment.
// http://anglebug.com/4889.
UNIMPLEMENTED();
break;
case EOpDFdx:
writeUnaryOp = spirv::WriteDPdx;
break;
case EOpDFdy:
writeUnaryOp = spirv::WriteDPdy;
break;
case EOpFwidth:
writeUnaryOp = spirv::WriteFwidth;
break;
case EOpDFdxFine:
writeUnaryOp = spirv::WriteDPdxFine;
break;
case EOpDFdyFine:
writeUnaryOp = spirv::WriteDPdyFine;
break;
case EOpDFdxCoarse:
writeUnaryOp = spirv::WriteDPdxCoarse;
break;
case EOpDFdyCoarse:
writeUnaryOp = spirv::WriteDPdyCoarse;
break;
case EOpFwidthFine:
writeUnaryOp = spirv::WriteFwidthFine;
break;
case EOpFwidthCoarse:
writeUnaryOp = spirv::WriteFwidthCoarse;
break;
// TODO: for the EOpInterpolate* built-ins, must convert interpolateX(vec.yz) to
// interpolate(vec).yz. This can either be done apriori by an AST transformation, or
// simply by taking the base id only when generating the instruction and keeping the
// indices/swizzle intact. http://anglebug.com/4889.
case EOpInterpolateAtCentroid:
extendedInst = spv::GLSLstd450InterpolateAtCentroid;
break;
case EOpInterpolateAtSample:
extendedInst = spv::GLSLstd450InterpolateAtSample;
break;
case EOpInterpolateAtOffset:
extendedInst = spv::GLSLstd450InterpolateAtOffset;
break;
case EOpNoise1:
case EOpNoise2:
case EOpNoise3:
case EOpNoise4:
// TODO: support desktop GLSL. http://anglebug.com/4889
UNIMPLEMENTED();
break;
case EOpSubpassLoad:
// TODO: support framebuffer fetch. http://anglebug.com/4889
UNIMPLEMENTED();
break;
case EOpAnyInvocation:
case EOpAllInvocations:
case EOpAllInvocationsEqual:
// TODO: support desktop GLSL. http://anglebug.com/4889
break;
default:
UNREACHABLE();
}
const SpirvDecorations decorations = mBuilder.getDecorations(node->getType());
spirv::IdRef result = mBuilder.getNewId(decorations);
// Load the parameters.
spirv::IdRefList parameters = loadAllParams(node);
if (operateOnColumns)
{
// If negating a matrix or multiplying them, do that column by column.
spirv::IdRefList columnIds;
const SpirvDecorations operandDecorations = mBuilder.getDecorations(firstOperandType);
SpirvType columnType = mBuilder.getSpirvType(firstOperandType, EbsUnspecified);
columnType.secondarySize = 1;
const spirv::IdRef columnTypeId = mBuilder.getSpirvTypeData(columnType, nullptr).id;
// Extract and apply the operator to each column.
for (int columnIndex = 0; columnIndex < firstOperandType.getCols(); ++columnIndex)
{
const spirv::IdRef columnIdA = mBuilder.getNewId(operandDecorations);
spirv::WriteCompositeExtract(mBuilder.getSpirvCurrentFunctionBlock(), columnTypeId,
columnIdA, parameters[0],
{spirv::LiteralInteger(columnIndex)});
columnIds.push_back(mBuilder.getNewId(decorations));
if (writeUnaryOp)
{
writeUnaryOp(mBuilder.getSpirvCurrentFunctionBlock(), columnTypeId,
columnIds.back(), columnIdA);
}
else
{
ASSERT(writeBinaryOp);
const spirv::IdRef columnIdB = mBuilder.getNewId(operandDecorations);
spirv::WriteCompositeExtract(mBuilder.getSpirvCurrentFunctionBlock(), columnTypeId,
columnIdB, parameters[1],
{spirv::LiteralInteger(columnIndex)});
writeBinaryOp(mBuilder.getSpirvCurrentFunctionBlock(), columnTypeId,
columnIds.back(), columnIdA, columnIdB);
}
}
// Construct the result.
spirv::WriteCompositeConstruct(mBuilder.getSpirvCurrentFunctionBlock(), resultTypeId,
result, columnIds);
}
else if (writeUnaryOp)
{
ASSERT(parameters.size() == 1);
writeUnaryOp(mBuilder.getSpirvCurrentFunctionBlock(), resultTypeId, result, parameters[0]);
}
else if (writeBinaryOp)
{
ASSERT(parameters.size() == 2);
// For vector<op>scalar operations that require it, turn the scalar into a vector of the
// same size.
if (binaryExtendScalarToVector)
{
const TType &leftType = node->getChildNode(0)->getAsTyped()->getType();
const TType &rightType = node->getChildNode(1)->getAsTyped()->getType();
if (leftType.isScalar() && rightType.isVector())
{
parameters[0] =
createConstructorVectorFromScalar(rightType, resultTypeId, {{parameters[0]}});
}
else if (rightType.isScalar() && leftType.isVector())
{
parameters[1] =
createConstructorVectorFromScalar(leftType, resultTypeId, {{parameters[1]}});
}
}
if (binarySwapOperands)
{
std::swap(parameters[0], parameters[1]);
}
// Write the operation that combines the left and right values.
writeBinaryOp(mBuilder.getSpirvCurrentFunctionBlock(), resultTypeId, result, parameters[0],
parameters[1]);
// If it's an assignment, store the calculated value.
if (IsAssignment(node->getOp()))
{
ASSERT(mNodeData.size() >= 2);
accessChainStore(&mNodeData[mNodeData.size() - 2], result);
}
}
else if (writeTernaryOp)
{
ASSERT(parameters.size() == 3);
// mix(a, b, bool) is the same as bool ? b : a;
if (op == EOpMix)
{
std::swap(parameters[0], parameters[2]);
}
writeTernaryOp(mBuilder.getSpirvCurrentFunctionBlock(), resultTypeId, result, parameters[0],
parameters[1], parameters[2]);
}
else if (writeQuaternaryOp)
{
ASSERT(parameters.size() == 4);
writeQuaternaryOp(mBuilder.getSpirvCurrentFunctionBlock(), resultTypeId, result,
parameters[0], parameters[1], parameters[2], parameters[3]);
}
else
{
// It's an extended instruction.
ASSERT(extendedInst != spv::GLSLstd450Bad);
spirv::WriteExtInst(mBuilder.getSpirvCurrentFunctionBlock(), resultTypeId, result,
mBuilder.getExtInstImportIdStd(),
spirv::LiteralExtInstInteger(extendedInst), parameters);
}
return result;
}
spirv::IdRef OutputSPIRVTraverser::createIncrementDecrement(TIntermOperator *node,
spirv::IdRef resultTypeId)
{
TIntermTyped *operand = node->getChildNode(0)->getAsTyped();
const TType &operandType = operand->getType();
const TBasicType basicType = operandType.getBasicType();
const bool isFloat = basicType == EbtFloat || basicType == EbtDouble;
// ++ and -- are implemented with binary SPIR-V ops.
WriteBinaryOp writeBinaryOp = nullptr;
switch (node->getOp())
{
case EOpPostIncrement:
case EOpPreIncrement:
if (isFloat)
writeBinaryOp = spirv::WriteFAdd;
else
writeBinaryOp = spirv::WriteIAdd;
break;
case EOpPostDecrement:
case EOpPreDecrement:
if (isFloat)
writeBinaryOp = spirv::WriteFSub;
else
writeBinaryOp = spirv::WriteISub;
break;
default:
UNREACHABLE();
}
// Load the operand.
spirv::IdRef value =
accessChainLoad(&mNodeData.back(), mBuilder.getDecorations(operand->getType()));
spirv::IdRef result = mBuilder.getNewId(mBuilder.getDecorations(operandType));
const spirv::IdRef one = isFloat ? mBuilder.getFloatConstant(1) : mBuilder.getIntConstant(1);
writeBinaryOp(mBuilder.getSpirvCurrentFunctionBlock(), resultTypeId, result, value, one);
// The result is always written back.
accessChainStore(&mNodeData.back(), result);
// Initialize the access chain with either the result or the value based on whether pre or
// post increment/decrement was used. The result is always an rvalue.
if (node->getOp() == EOpPostIncrement || node->getOp() == EOpPostDecrement)
{
result = value;
}
return result;
}
spirv::IdRef OutputSPIRVTraverser::createAtomicBuiltIn(TIntermOperator *node,
spirv::IdRef resultTypeId)
{
// Most atomic instructions are in the form of:
//
// %result = OpAtomicX %pointer Scope MemorySemantics %value
//
// OpAtomicCompareSwap is exceptionally different (note that compare and value are in different
// order than in GLSL):
//
// %result = OpAtomicCompareExchange %pointer
// Scope MemorySemantics MemorySemantics
// %value %comparator
//
// In all cases, the first parameter is the pointer, and the rest are rvalues.
const size_t parameterCount = node->getChildCount();
spirv::IdRef pointerId;
spirv::IdRefList parameters;
ASSERT(parameterCount >= 2);
pointerId = accessChainCollapse(&mNodeData[mNodeData.size() - parameterCount]);
for (size_t paramIndex = 1; paramIndex < parameterCount; ++paramIndex)
{
NodeData &param = mNodeData[mNodeData.size() - parameterCount + paramIndex];
parameters.push_back(accessChainLoad(
&param,
mBuilder.getDecorations(node->getChildNode(paramIndex)->getAsTyped()->getType())));
}
// The scope of the operation is always Device as we don't enable the Vulkan memory model
// extension.
const spirv::IdScope scopeId = mBuilder.getUintConstant(spv::ScopeDevice);
// The memory semantics is always relaxed as we don't enable the Vulkan memory model extension.
const spirv::IdMemorySemantics semanticsId =
mBuilder.getUintConstant(spv::MemorySemanticsMaskNone);
WriteAtomicOp writeAtomicOp = nullptr;
const spirv::IdRef result = mBuilder.getNewId(mBuilder.getDecorations(node->getType()));
// TODO: determine isUnsigned correctly for image types. Should rearrange TBasicType enums to
// group images based on basic type and do range check. http://anglebug.com/4889.
const bool isUnsigned =
node->getChildNode(0)->getAsTyped()->getType().getBasicType() == EbtUInt;
switch (node->getOp())
{
case EOpAtomicAdd:
case EOpImageAtomicAdd:
writeAtomicOp = spirv::WriteAtomicIAdd;
break;
case EOpAtomicMin:
case EOpImageAtomicMin:
writeAtomicOp = isUnsigned ? spirv::WriteAtomicUMin : spirv::WriteAtomicSMin;
break;
case EOpAtomicMax:
case EOpImageAtomicMax:
writeAtomicOp = isUnsigned ? spirv::WriteAtomicUMax : spirv::WriteAtomicSMax;
break;
case EOpAtomicAnd:
case EOpImageAtomicAnd:
writeAtomicOp = spirv::WriteAtomicAnd;
break;
case EOpAtomicOr:
case EOpImageAtomicOr:
writeAtomicOp = spirv::WriteAtomicOr;
break;
case EOpAtomicXor:
case EOpImageAtomicXor:
writeAtomicOp = spirv::WriteAtomicXor;
break;
case EOpAtomicExchange:
case EOpImageAtomicExchange:
writeAtomicOp = spirv::WriteAtomicExchange;
break;
case EOpAtomicCompSwap:
case EOpImageAtomicCompSwap:
// Generate this special instruction right here and early out. Note again that the
// value and compare parameters of OpAtomicCompareExchange are in the opposite order
// from GLSL.
ASSERT(parameters.size() == 2);
spirv::WriteAtomicCompareExchange(mBuilder.getSpirvCurrentFunctionBlock(), resultTypeId,
result, pointerId, scopeId, semanticsId, semanticsId,
parameters[1], parameters[0]);
return result;
default:
UNREACHABLE();
}
// Write the instruction.
ASSERT(parameters.size() == 1);
writeAtomicOp(mBuilder.getSpirvCurrentFunctionBlock(), resultTypeId, result, pointerId, scopeId,
semanticsId, parameters[0]);
return result;
}
spirv::IdRef OutputSPIRVTraverser::createTextureBuiltIn(TIntermOperator *node,
spirv::IdRef resultTypeId)
{
// TODO: http://anglebug.com/4889
UNIMPLEMENTED();
return spirv::IdRef{};
}
spirv::IdRef OutputSPIRVTraverser::createImageBuiltIn(TIntermOperator *node,
spirv::IdRef resultTypeId)
{
// TODO: http://anglebug.com/4889
UNIMPLEMENTED();
return spirv::IdRef{};
}
void OutputSPIRVTraverser::visitSymbol(TIntermSymbol *node)
{
// Constants are expected to be folded.
ASSERT(!node->hasConstantValue());
// No-op visits to symbols that are being declared. They are handled in visitDeclaration.
if (mIsSymbolBeingDeclared)
{
// Make sure this does not affect other symbols, for example in the initializer expression.
mIsSymbolBeingDeclared = false;
return;
}
mNodeData.emplace_back();
// The symbol is either:
//
// - A specialization constant
// - A variable (local, varying etc)
// - An interface block
// - A field of an unnamed interface block
//
// Specialization constants in SPIR-V are treated largely like constants, in which case make
// this behave like visitConstantUnion().
const TType &type = node->getType();
const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();
const TSymbol *symbol = interfaceBlock;
if (interfaceBlock == nullptr)
{
symbol = &node->variable();
}
// Track the block storage; it's needed to determine the derived type in an access chain, but is
// not promoted in intermediate nodes' TType.
TLayoutBlockStorage blockStorage = EbsUnspecified;
if (interfaceBlock)
{
blockStorage = mBuilder.getBlockStorage(type);
}
const spirv::IdRef typeId = mBuilder.getTypeData(type, blockStorage).id;
// If the symbol is a const variable, such as a const function parameter or specialization
// constant, create an rvalue.
if (type.getQualifier() == EvqConst || type.getQualifier() == EvqSpecConst)
{
ASSERT(mSymbolIdMap.count(symbol) > 0);
nodeDataInitRValue(&mNodeData.back(), mSymbolIdMap[symbol], typeId);
return;
}
// Otherwise create an lvalue.
spv::StorageClass storageClass;
const spirv::IdRef symbolId = getSymbolIdAndStorageClass(symbol, type, &storageClass);
nodeDataInitLValue(&mNodeData.back(), symbolId, typeId, storageClass, blockStorage);
// If a field of a nameless interface block, create an access chain.
if (interfaceBlock && !type.isInterfaceBlock())
{
uint32_t fieldIndex = static_cast<uint32_t>(type.getInterfaceBlockFieldIndex());
accessChainPushLiteral(&mNodeData.back(), spirv::LiteralInteger(fieldIndex), typeId);
}
}
void OutputSPIRVTraverser::visitConstantUnion(TIntermConstantUnion *node)
{
mNodeData.emplace_back();
const TType &type = node->getType();
// Find out the expected type for this constant, so it can be cast right away and not need an
// instruction to do that.
TIntermNode *parent = getParentNode();
const size_t childIndex = getParentChildIndex(PreVisit);
TBasicType expectedBasicType = type.getBasicType();
if (parent->getAsAggregate())
{
TIntermAggregate *parentAggregate = parent->getAsAggregate();
// There are three possibilities:
//
// - It's a struct constructor: The basic type must match that of the corresponding field of
// the struct.
// - It's a non struct constructor: The basic type must match that of the the type being
// constructed.
// - It's a function call: The basic type must match that of the corresponding argument.
if (parentAggregate->isConstructor())
{
const TStructure *structure = parentAggregate->getType().getStruct();
if (structure != nullptr)
{
expectedBasicType = structure->fields()[childIndex]->type()->getBasicType();
}
else
{
expectedBasicType = parentAggregate->getType().getBasicType();
}
}
else
{
expectedBasicType =
parentAggregate->getFunction()->getParam(childIndex)->getType().getBasicType();
}
}
// TODO: other node types such as binary, ternary etc. http://anglebug.com/4889
const spirv::IdRef typeId = mBuilder.getTypeData(type, EbsUnspecified).id;
const spirv::IdRef constId = createConstant(type, expectedBasicType, node->getConstantValue());
nodeDataInitRValue(&mNodeData.back(), constId, typeId);
}
bool OutputSPIRVTraverser::visitSwizzle(Visit visit, TIntermSwizzle *node)
{
// Constants are expected to be folded.
ASSERT(!node->hasConstantValue());
if (visit == PreVisit)
{
// Don't add an entry to the stack. The child will create one, which we won't pop.
return true;
}
case EOpPackUnorm4x8:
extendedInst = spv::GLSLstd450PackUnorm4x8;
break;
case EOpPackSnorm4x8:
extendedInst = spv::GLSLstd450PackSnorm4x8;
break;
case EOpUnpackUnorm4x8:
extendedInst = spv::GLSLstd450UnpackUnorm4x8;
break;
case EOpUnpackSnorm4x8:
extendedInst = spv::GLSLstd450UnpackSnorm4x8;
break;
ASSERT(visit == PostVisit);
ASSERT(mNodeData.size() >= 1);
case EOpLength:
extendedInst = spv::GLSLstd450Length;
break;
case EOpNormalize:
extendedInst = spv::GLSLstd450Normalize;
break;
const TType &vectorType = node->getOperand()->getType();
const uint8_t vectorComponentCount = static_cast<uint8_t>(vectorType.getNominalSize());
const TVector<int> &swizzle = node->getSwizzleOffsets();
case EOpDFdx:
writeUnaryOp = spirv::WriteDPdx;
break;
case EOpDFdy:
writeUnaryOp = spirv::WriteDPdy;
break;
case EOpFwidth:
writeUnaryOp = spirv::WriteFwidth;
break;
// As an optimization, do nothing if the swizzle is selecting all the components of the vector
// in order.
bool isIdentity = swizzle.size() == vectorComponentCount;
for (size_t index = 0; index < swizzle.size(); ++index)
{
isIdentity = isIdentity && static_cast<size_t>(swizzle[index]) == index;
}
case EOpTranspose:
writeUnaryOp = spirv::WriteTranspose;
break;
case EOpDeterminant:
extendedInst = spv::GLSLstd450Determinant;
break;
case EOpInverse:
extendedInst = spv::GLSLstd450MatrixInverse;
break;
if (isIdentity)
{
return true;
}
case EOpAny:
writeUnaryOp = spirv::WriteAny;
break;
case EOpAll:
writeUnaryOp = spirv::WriteAll;
break;
const spirv::IdRef typeId =
mBuilder.getTypeData(node->getType(), mNodeData.back().accessChain.baseBlockStorage).id;
case EOpBitfieldReverse:
writeUnaryOp = spirv::WriteBitReverse;
break;
case EOpBitCount:
writeUnaryOp = spirv::WriteBitCount;
break;
case EOpFindLSB:
extendedInst = spv::GLSLstd450FindILsb;
break;
case EOpFindMSB:
if (isUnsigned)
extendedInst = spv::GLSLstd450FindUMsb;
else
extendedInst = spv::GLSLstd450FindSMsb;
break;
accessChainPushSwizzle(&mNodeData.back(), swizzle, typeId, vectorComponentCount);
default:
UNREACHABLE();
return true;
}
bool OutputSPIRVTraverser::visitBinary(Visit visit, TIntermBinary *node)
{
// Constants are expected to be folded.
ASSERT(!node->hasConstantValue());
if (visit == PreVisit)
{
// Don't add an entry to the stack. The left child will create one, which we won't pop.
return true;
}
const SpirvDecorations decorations = mBuilder.getDecorations(operandType);
spirv::IdRef result = mBuilder.getNewId(decorations);
// If this is a variable initialization node, defer any code generation to visitDeclaration.
if (node->getOp() == EOpInitialize)
{
ASSERT(getParentNode()->getAsDeclarationNode() != nullptr);
return true;
}
if (writeUnaryOp)
if (IsShortCircuitNeeded(node))
{
if (operateOnColumns)
// For && and ||, if short-circuiting behavior is needed, we need to emulate it with an
// |if| construct. At this point, the left-hand side is already evaluated, so we need to
// create an appropriate conditional on in-visit and visit the right-hand-side inside the
// conditional block. On post-visit, OpPhi is used to calculate the result.
if (visit == InVisit)
{
// If negating a matrix, do that column by column.
spirv::IdRefList columnIds;
startShortCircuit(node);
return true;
}
SpirvType columnType = mBuilder.getSpirvType(operandType, EbsUnspecified);
columnType.secondarySize = 1;
const spirv::IdRef columnTypeId = mBuilder.getSpirvTypeData(columnType, nullptr).id;
spirv::IdRef typeId;
const spirv::IdRef result = endShortCircuit(node, &typeId);
// Extract and apply the operator to each column.
for (int columnIndex = 0; columnIndex < operandType.getCols(); ++columnIndex)
{
const spirv::IdRef columnId = mBuilder.getNewId(decorations);
spirv::WriteCompositeExtract(mBuilder.getSpirvCurrentFunctionBlock(), columnTypeId,
columnId, value, {spirv::LiteralInteger(columnIndex)});
// Replace the access chain with an rvalue that's the result.
nodeDataInitRValue(&mNodeData.back(), result, typeId);
columnIds.push_back(mBuilder.getNewId(decorations));
writeUnaryOp(mBuilder.getSpirvCurrentFunctionBlock(), columnTypeId,
columnIds.back(), columnId);
}
return true;
}
// Construct the result.
spirv::WriteCompositeConstruct(mBuilder.getSpirvCurrentFunctionBlock(), typeId, result,
columnIds);
}
else
if (visit == InVisit)
{
// Left child visited. Take the entry it created as the current node's.
ASSERT(mNodeData.size() >= 1);
// As an optimization, if the index is EOpIndexDirect*, take the constant index directly and
// add it to the access chain as literal.
switch (node->getOp())
{
// Otherwise just apply the operation.
writeUnaryOp(mBuilder.getSpirvCurrentFunctionBlock(), typeId, result, value);
case EOpIndexDirect:
case EOpIndexDirectStruct:
case EOpIndexDirectInterfaceBlock:
accessChainPushLiteral(
&mNodeData.back(),
spirv::LiteralInteger(node->getRight()->getAsConstantUnion()->getIConst(0)),
mBuilder
.getTypeData(node->getType(), mNodeData.back().accessChain.baseBlockStorage)
.id);
// Don't visit the right child, it's already processed.
return false;
default:
break;
}
return true;
}
else if (writeBinaryOp)
// There are at least two entries, one for the left node and one for the right one.
ASSERT(mNodeData.size() >= 2);
TLayoutBlockStorage blockStorage = EbsUnspecified;
if (node->getOp() == EOpIndexIndirect || node->getOp() == EOpAssign)
{
// It's a pre/post increment/decrement.
const spirv::IdRef one =
isFloat ? mBuilder.getFloatConstant(1) : mBuilder.getIntConstant(1);
blockStorage = mNodeData[mNodeData.size() - 2].accessChain.baseBlockStorage;
}
const spirv::IdRef resultTypeId = mBuilder.getTypeData(node->getType(), blockStorage).id;
writeBinaryOp(mBuilder.getSpirvCurrentFunctionBlock(), typeId, result, value, one);
// For EOpIndex* operations, push the right value as an index to the left value's access chain.
// For the other operations, evaluate the expression.
switch (node->getOp())
{
case EOpIndexDirect:
case EOpIndexDirectStruct:
case EOpIndexDirectInterfaceBlock:
UNREACHABLE();
break;
case EOpIndexIndirect:
{
// Load the index.
const spirv::IdRef rightValue = accessChainLoad(
&mNodeData.back(), mBuilder.getDecorations(node->getRight()->getType()));
mNodeData.pop_back();
// The result is always written back.
accessChainStore(&mNodeData.back(), result);
if (!node->getLeft()->getType().isArray() && node->getLeft()->getType().isVector())
{
accessChainPushDynamicComponent(&mNodeData.back(), rightValue, resultTypeId);
}
else
{
accessChainPush(&mNodeData.back(), rightValue, resultTypeId);
}
break;
}
// Initialize the access chain with either the result or the value based on whether pre or
// post increment/decrement was used. The result is always an rvalue.
if (node->getOp() == EOpPostIncrement || node->getOp() == EOpPostDecrement)
case EOpAssign:
{
result = value;
// Load the right hand side of assignment.
const spirv::IdRef rightValue = accessChainLoad(
&mNodeData.back(), mBuilder.getDecorations(node->getRight()->getType()));
mNodeData.pop_back();
// Store into the access chain. Since the result of the (a = b) expression is b, change
// the access chain to an unindexed rvalue which is |rightValue|.
// TODO: handle mismatching types. http://anglebug.com/4889.
accessChainStore(&mNodeData.back(), rightValue);
nodeDataInitRValue(&mNodeData.back(), rightValue, resultTypeId);
break;
}
case EOpComma:
// When the expression a,b is visited, all side effects of a and b are already
// processed. What's left is to to replace the expression with the result of b. This
// is simply done by dropping the left node and placing the right node as the result.
mNodeData.erase(mNodeData.begin() + mNodeData.size() - 2);
break;
default:
const spirv::IdRef result = visitOperator(node, resultTypeId);
mNodeData.pop_back();
nodeDataInitRValue(&mNodeData.back(), result, resultTypeId);
// TODO: Handle NoContraction decoration. http://anglebug.com/4889
break;
}
else
return true;
}
bool OutputSPIRVTraverser::visitUnary(Visit visit, TIntermUnary *node)
{
// Constants are expected to be folded.
ASSERT(!node->hasConstantValue());
if (visit == PreVisit)
{
// It's an extended instruction.
ASSERT(extendedInst != spv::GLSLstd450Bad);
// Don't add an entry to the stack. The child will create one, which we won't pop.
return true;
}
spirv::WriteExtInst(mBuilder.getSpirvCurrentFunctionBlock(), typeId, result,
mBuilder.getExtInstImportIdStd(),
spirv::LiteralExtInstInteger(extendedInst), {value});
// It's a unary operation, so there can't be an InVisit.
ASSERT(visit != InVisit);
// There is at least on entry for the child.
ASSERT(mNodeData.size() >= 1);
// Special case EOpArrayLength. .length() on sized arrays is already constant folded, so this
// operation only applies to ssbo.last_member.length(). OpArrayLength takes the ssbo block
// *type* and the field index of last_member, so those need to be extracted from the access
// chain. Additionally, OpArrayLength produces an unsigned int while GLSL produces an int, so a
// final cast is necessary.
if (node->getOp() == EOpArrayLength)
{
// The access chain must only include the base ssbo + one literal field index.
ASSERT(mNodeData.back().idList.size() == 1 && !mNodeData.back().idList.back().id.valid());
const spirv::LiteralInteger fieldIndex = mNodeData.back().idList.back().literal;
// Get the interface block type from the operand, which is either a symbol or a binary
// operator based on whether the interface block is nameless or not.
TIntermTyped *operand = node->getOperand();
TIntermTyped *ssbo =
operand->getAsBinaryNode() ? operand->getAsBinaryNode()->getLeft() : operand;
const spirv::IdRef typeId = mBuilder.getTypeData(ssbo->getType(), EbsUnspecified).id;
// Get the int and uint type ids.
SpirvType intType;
intType.type = EbtInt;
const spirv::IdRef intTypeId = mBuilder.getSpirvTypeData(intType, nullptr).id;
intType.type = EbtUInt;
const spirv::IdRef uintTypeId = mBuilder.getSpirvTypeData(intType, nullptr).id;
// Generate the instruction.
const spirv::IdRef resultId = mBuilder.getNewId({});
spirv::WriteArrayLength(mBuilder.getSpirvCurrentFunctionBlock(), uintTypeId, resultId,
typeId, fieldIndex);
// Cast to int.
const spirv::IdRef castResultId = mBuilder.getNewId({});
spirv::WriteBitcast(mBuilder.getSpirvCurrentFunctionBlock(), intTypeId, castResultId,
resultId);
// Replace the access chain with an rvalue that's the result.
nodeDataInitRValue(&mNodeData.back(), castResultId, intTypeId);
return true;
}
nodeDataInitRValue(&mNodeData.back(), result, typeId);
const spirv::IdRef resultTypeId = mBuilder.getTypeData(node->getType(), EbsUnspecified).id;
const spirv::IdRef result = visitOperator(node, resultTypeId);
// Keep the result as rvalue.
nodeDataInitRValue(&mNodeData.back(), result, resultTypeId);
return true;
}
......@@ -2785,42 +3127,50 @@ bool OutputSPIRVTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
// Expect to have accumulated as many parameters as the node requires.
ASSERT(mNodeData.size() > node->getChildCount());
const spirv::IdRef typeId = mBuilder.getTypeData(node->getType(), EbsUnspecified).id;
const spirv::IdRef resultTypeId = mBuilder.getTypeData(node->getType(), EbsUnspecified).id;
spirv::IdRef result;
switch (node->getOp())
{
case EOpConstruct:
// Construct a value out of the accumulated parameters.
result = createConstructor(node, typeId);
result = createConstructor(node, resultTypeId);
break;
case EOpCallFunctionInAST:
// Create a call to the function.
result = createFunctionCall(node, typeId);
result = createFunctionCall(node, resultTypeId);
break;
case EOpMemoryBarrier:
case EOpMemoryBarrierAtomicCounter:
case EOpMemoryBarrierBuffer:
case EOpMemoryBarrierImage:
case EOpBarrier:
case EOpMemoryBarrierShared:
case EOpGroupMemoryBarrier:
case EOpBarrierTCS:
// TODO: support barriers. http://anglebug.com/4889
UNIMPLEMENTED();
break;
case EOpAtomicAdd:
case EOpAtomicMin:
case EOpAtomicMax:
case EOpAtomicAnd:
case EOpAtomicOr:
case EOpAtomicXor:
case EOpAtomicExchange:
case EOpAtomicCompSwap:
result = createAtomicBuiltIn(node, typeId);
case EOpEmitVertex:
case EOpEndPrimitive:
case EOpEmitStreamVertex:
case EOpEndStreamPrimitive:
// TODO: support geometry shaders. http://anglebug.com/4889
UNIMPLEMENTED();
break;
default:
// TODO: More built-in functions. http://anglebug.com/4889
UNIMPLEMENTED();
result = visitOperator(node, resultTypeId);
break;
}
// Pop the parameters.
mNodeData.resize(mNodeData.size() - node->getChildCount());
// If the function has a return value, take the return value as the result.
if (node->getType().getBasicType() != EbtVoid)
{
nodeDataInitRValue(&mNodeData.back(), result, typeId);
}
// Keep the result as rvalue.
nodeDataInitRValue(&mNodeData.back(), result, resultTypeId);
return false;
}
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -387,546 +387,547 @@ GROUP BEGIN Math {"queryFunction": true}
GROUP END Integer
GROUP END Math
GROUP BEGIN TextureFirstVersions
DEFAULT METADATA {"essl_level": "ESSL1_BUILTINS", "glsl_level": "COMMON_BUILTINS", "hasSideEffects": "true"}
vec4 texture2D(sampler2D, vec2);
vec4 texture2DProj(sampler2D, vec3);
vec4 texture2DProj(sampler2D, vec4);
vec4 textureCube(samplerCube, vec3);
DEFAULT METADATA {"glsl_level": "COMMON_BUILTINS", "hasSideEffects": "true"}
vec4 texture1D(sampler1D, float);
vec4 texture1DProj(sampler1D, vec2);
vec4 texture1DProj(sampler1D, vec4);
vec4 texture3D(sampler3D, vec3);
vec4 texture3DProj(sampler3D, vec4);
vec4 shadow1D(sampler1DShadow, vec3);
vec4 shadow1DProj(sampler1DShadow, vec4);
vec4 shadow2D(sampler2DShadow, vec3);
vec4 shadow2DProj(sampler2DShadow, vec4);
DEFAULT METADATA {"essl_level": "ESSL1_BUILTINS", "essl_extension": "OES_EGL_image_external, NV_EGL_stream_consumer_external", "hasSideEffects": "true"}
vec4 texture2D(samplerExternalOES, vec2);
vec4 texture2DProj(samplerExternalOES, vec3);
vec4 texture2DProj(samplerExternalOES, vec4);
GROUP END TextureFirstVersions
GROUP BEGIN Texture {"queryFunction": true}
GROUP BEGIN FirstVersions
DEFAULT METADATA {"essl_level": "ESSL1_BUILTINS", "glsl_level": "COMMON_BUILTINS", "hasSideEffects": "true"}
vec4 texture2D(sampler2D, vec2);
vec4 texture2DProj(sampler2D, vec3);
vec4 texture2DProj(sampler2D, vec4);
vec4 textureCube(samplerCube, vec3);
DEFAULT METADATA {"glsl_level": "COMMON_BUILTINS", "hasSideEffects": "true"}
vec4 texture1D(sampler1D, float);
vec4 texture1DProj(sampler1D, vec2);
vec4 texture1DProj(sampler1D, vec4);
vec4 texture3D(sampler3D, vec3);
vec4 texture3DProj(sampler3D, vec4);
vec4 shadow1D(sampler1DShadow, vec3);
vec4 shadow1DProj(sampler1DShadow, vec4);
vec4 shadow2D(sampler2DShadow, vec3);
vec4 shadow2DProj(sampler2DShadow, vec4);
DEFAULT METADATA {"essl_level": "ESSL1_BUILTINS", "essl_extension": "OES_EGL_image_external, NV_EGL_stream_consumer_external", "hasSideEffects": "true"}
vec4 texture2D(samplerExternalOES, vec2);
vec4 texture2DProj(samplerExternalOES, vec3);
vec4 texture2DProj(samplerExternalOES, vec4);
DEFAULT METADATA {"essl_level": "ESSL1_BUILTINS", "hasSideEffects": "true", "essl_extension": "ARB_texture_rectangle"}
vec4 texture2DRect(sampler2DRect, vec2);
vec4 texture2DRectProj(sampler2DRect, vec3);
vec4 texture2DRectProj(sampler2DRect, vec4);
// The *Grad* variants are new to both vertex and fragment shaders; the fragment
// shader specific pieces are added separately below.
DEFAULT METADATA {"essl_level": "ESSL1_BUILTINS", "hasSideEffects": "true", "essl_extension": "EXT_shader_texture_lod"}
vec4 texture2DGradEXT(sampler2D, vec2, vec2, vec2);
vec4 texture2DProjGradEXT(sampler2D, vec3, vec2, vec2);
vec4 texture2DProjGradEXT(sampler2D, vec4, vec2, vec2);
vec4 textureCubeGradEXT(samplerCube, vec3, vec3, vec3);
DEFAULT METADATA {"essl_level": "ESSL1_BUILTINS", "glsl_level": "COMMON_BUILTINS", "hasSideEffects": "true", "extension": "WEBGL_video_texture"}
vec4 textureVideoWEBGL(samplerVideoWEBGL, vec2);
GROUP END FirstVersions
GROUP BEGIN ARB_texture_rectangle
DEFAULT METADATA {"essl_level": "ESSL1_BUILTINS", "hasSideEffects": "true", "essl_extension": "ARB_texture_rectangle"}
vec4 texture2DRect(sampler2DRect, vec2);
vec4 texture2DRectProj(sampler2DRect, vec3);
vec4 texture2DRectProj(sampler2DRect, vec4);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "opSuffix": "Rect", "hasSideEffects": "true", "essl_extension": "ARB_texture_rectangle"}
// We don't have a rectangle texture essl_extension for OpenGL ES however based on the behavior of
// rectangle texture in desktop OpenGL, they should be sampled with a "texture" overload in
// GLSL version that have such an overload. This is the case for ESSL3 and above.
vec4 texture(sampler2DRect, vec2);
vec4 textureProj(sampler2DRect, vec3);
vec4 textureProj(sampler2DRect, vec4);
GROUP END ARB_texture_rectangle
GROUP BEGIN FirstVersionsFS {"shader_type": "FRAGMENT", "opSuffix": "FS"}
DEFAULT METADATA {"essl_level": "ESSL1_BUILTINS", "glsl_level": "COMMON_BUILTINS", "hasSideEffects": "true"}
vec4 texture2D(sampler2D, vec2, float);
vec4 texture2DProj(sampler2D, vec3, float);
vec4 texture2DProj(sampler2D, vec4, float);
vec4 textureCube(samplerCube, vec3, float);
DEFAULT METADATA {"glsl_level": "COMMON_BUILTINS", "hasSideEffects": "true"}
vec4 texture3D(sampler3D, vec3, float);
vec4 texture3DProj(sampler3D, vec4, float);
vec4 texture3DLod(sampler3D, vec3, float);
vec4 texture3DProjLod(sampler3D, vec4, float);
vec4 texture1D(sampler1D, float, float);
vec4 texture1DProj(sampler1D, vec2, float);
vec4 texture1DProj(sampler1D, vec4, float);
vec4 shadow1D(sampler1DShadow, vec3, float);
vec4 shadow1DProj(sampler1DShadow, vec4, float);
vec4 shadow2D(sampler2DShadow, vec3, float);
vec4 shadow2DProj(sampler2DShadow, vec4, float);
GROUP END FirstVersionsFS
// The *Grad* variants are new to both vertex and fragment shaders; the fragment
// shader specific pieces are added separately below.
GROUP BEGIN EXT_shader_texture_lod
DEFAULT METADATA {"essl_level": "ESSL1_BUILTINS", "hasSideEffects": "true", "essl_extension": "EXT_shader_texture_lod"}
vec4 texture2DGradEXT(sampler2D, vec2, vec2, vec2);
vec4 texture2DProjGradEXT(sampler2D, vec3, vec2, vec2);
vec4 texture2DProjGradEXT(sampler2D, vec4, vec2, vec2);
vec4 textureCubeGradEXT(samplerCube, vec3, vec3, vec3);
GROUP END EXT_shader_texture_lod
GROUP BEGIN FirstVersionsFSExt {"shader_type": "FRAGMENT", "opSuffix": "FSExt"}
DEFAULT METADATA {"essl_level": "ESSL1_BUILTINS", "hasSideEffects": "true", "essl_extension": "EXT_shader_texture_lod"}
vec4 texture2DLodEXT(sampler2D, vec2, float);
vec4 texture2DProjLodEXT(sampler2D, vec3, float);
vec4 texture2DProjLodEXT(sampler2D, vec4, float);
vec4 textureCubeLodEXT(samplerCube, vec3, float);
DEFAULT METADATA {"essl_level": "ESSL1_BUILTINS", "hasSideEffects": "true", "essl_extension": "EXT_shadow_samplers"}
float shadow2DEXT(sampler2DShadow, vec3);
float shadow2DProjEXT(sampler2DShadow, vec4);
DEFAULT METADATA {"essl_level": "ESSL1_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_texture_3D"}
vec4 texture3D(sampler3D, vec3);
vec4 texture3DProj(sampler3D, vec4);
DEFAULT METADATA {"essl_level": "ESSL1_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_texture_3D"}
vec4 texture3D(sampler3D, vec3, float);
vec4 texture3DProj(sampler3D, vec4, float);
DEFAULT METADATA {"essl_level": "ESSL1_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_texture_3D"}
vec4 texture3DLod(sampler3D, vec3, float);
vec4 texture3DProjLod(sampler3D, vec4, float);
GROUP END FirstVersionsFSExt
GROUP BEGIN TextureFirstVersionsFS {"shader_type": "FRAGMENT", "opSuffix": "FS"}
DEFAULT METADATA {"essl_level": "ESSL1_BUILTINS", "glsl_level": "COMMON_BUILTINS", "hasSideEffects": "true"}
vec4 texture2D(sampler2D, vec2, float);
vec4 texture2DProj(sampler2D, vec3, float);
vec4 texture2DProj(sampler2D, vec4, float);
vec4 textureCube(samplerCube, vec3, float);
DEFAULT METADATA {"glsl_level": "COMMON_BUILTINS", "hasSideEffects": "true"}
vec4 texture3D(sampler3D, vec3, float);
vec4 texture3DProj(sampler3D, vec4, float);
vec4 texture3DLod(sampler3D, vec3, float);
vec4 texture3DProjLod(sampler3D, vec4, float);
vec4 texture1D(sampler1D, float, float);
vec4 texture1DProj(sampler1D, vec2, float);
vec4 texture1DProj(sampler1D, vec4, float);
vec4 shadow1D(sampler1DShadow, vec3, float);
vec4 shadow1DProj(sampler1DShadow, vec4, float);
vec4 shadow2D(sampler2DShadow, vec3, float);
vec4 shadow2DProj(sampler2DShadow, vec4, float);
GROUP END TextureFirstVersionsFS
GROUP BEGIN FirstVersionsVS {"shader_type": "VERTEX"}
DEFAULT METADATA {"essl_level": "ESSL1_BUILTINS", "glsl_level": "COMMON_BUILTINS", "hasSideEffects": "true"}
vec4 texture2DLod(sampler2D, vec2, float);
vec4 texture2DProjLod(sampler2D, vec3, float);
vec4 texture2DProjLod(sampler2D, vec4, float);
vec4 textureCubeLod(samplerCube, vec3, float);
DEFAULT METADATA {"glsl_level": "COMMON_BUILTINS", "hasSideEffects": "true"}
vec4 texture1DLod(sampler1D, float, float);
vec4 texture1DProjLod(sampler1D, vec2, float);
vec4 texture1DProjLod(sampler1D, vec4, float);
vec4 shadow1DLod(sampler1DShadow, vec3, float);
vec4 shadow1DProjLod(sampler1DShadow, vec4, float);
vec4 shadow2DLod(sampler2DShadow, vec3, float);
vec4 shadow2DProjLod(sampler2DShadow, vec4, float);
GROUP END FirstVersionsVS
GROUP BEGIN TextureFirstVersionsFSExt {"shader_type": "FRAGMENT", "opSuffix": "FSExt"}
DEFAULT METADATA {"essl_level": "ESSL1_BUILTINS", "hasSideEffects": "true", "essl_extension": "EXT_shader_texture_lod"}
vec4 texture2DLodEXT(sampler2D, vec2, float);
vec4 texture2DProjLodEXT(sampler2D, vec3, float);
vec4 texture2DProjLodEXT(sampler2D, vec4, float);
vec4 textureCubeLodEXT(samplerCube, vec3, float);
DEFAULT METADATA {"essl_level": "ESSL1_BUILTINS", "hasSideEffects": "true", "essl_extension": "EXT_shadow_samplers"}
float shadow2DEXT(sampler2DShadow, vec3);
float shadow2DProjEXT(sampler2DShadow, vec4);
DEFAULT METADATA {"essl_level": "ESSL1_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_texture_3D"}
vec4 texture3D(sampler3D, vec3);
vec4 texture3DProj(sampler3D, vec4);
DEFAULT METADATA {"essl_level": "ESSL1_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_texture_3D"}
vec4 texture3D(sampler3D, vec3, float);
vec4 texture3DProj(sampler3D, vec4, float);
DEFAULT METADATA {"essl_level": "ESSL1_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_texture_3D"}
vec4 texture3DLod(sampler3D, vec3, float);
vec4 texture3DProjLod(sampler3D, vec4, float);
GROUP END TextureFirstVersionsFSExt
GROUP BEGIN NoBias
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 texture(gsampler2D, vec2);
gvec4 texture(gsampler3D, vec3);
gvec4 texture(gsamplerCube, vec3);
gvec4 texture(gsampler2DArray, vec3);
float texture(sampler2DShadow, vec3);
float texture(samplerCubeShadow, vec4);
float texture(sampler2DArrayShadow, vec4);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 texture(gsampler1D, float);
float texture(sampler1DShadow, vec3);
gvec4 texture(gsampler1DArray, vec3);
float texture(sampler1DArrayShadow, vec3);
DEFAULT METADATA {"glsl_level": "GLSL1_4_BUILTINS", "hasSideEffects": "true"}
gvec4 texture(gsampler2DRect, vec2);
float texture(sampler2DRectShadow, vec3);
DEFAULT METADATA {"essl_level": "ESSL3_2_BUILTINS", "glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
gvec4 texture(gsamplerCubeArray, vec4);
gvec4 texture(gsamplerCubeArray, vec4, float);
float texture(samplerCubeArrayShadow, vec4, float);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_texture_cube_map_array, EXT_texture_cube_map_array", "suffix": "Ext"}
gvec4 texture(gsamplerCubeArray, vec4);
gvec4 texture(gsamplerCubeArray, vec4, float);
float texture(samplerCubeArrayShadow, vec4, float);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_EGL_image_external_essl3"}
vec4 texture(samplerExternalOES, vec2);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "hasSideEffects": "true", "essl_extension": "EXT_YUV_target"}
vec4 texture(samplerExternal2DY2YEXT, vec2);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "opSuffix": "Rect", "hasSideEffects": "true", "essl_extension": "ARB_texture_rectangle"}
// We don't have a rectangle texture essl_extension for OpenGL ES however based on the behavior of
// rectangle texture in desktop OpenGL, they should be sampled with a "texture" overload in
// GLSL version that have such an overload. This is the case for ESSL3 and above.
vec4 texture(sampler2DRect, vec2);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true", "extension": "WEBGL_video_texture"}
vec4 texture(samplerVideoWEBGL, vec2);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProj(gsampler2D, vec3);
gvec4 textureProj(gsampler2D, vec4);
gvec4 textureProj(gsampler3D, vec4);
float textureProj(sampler2DShadow, vec4);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProj(gsampler1D, vec2);
gvec4 textureProj(gsampler1D, vec4);
float textureProj(sampler1DShadow, vec4);
DEFAULT METADATA {"glsl_level": "GLSL1_4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProj(gsampler2DRect, vec3);
gvec4 textureProj(gsampler2DRect, vec4);
float textureProj(sampler2DRectShadow, vec4);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_EGL_image_external_essl3"}
vec4 textureProj(samplerExternalOES, vec3);
vec4 textureProj(samplerExternalOES, vec4);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "hasSideEffects": "true", "essl_extension": "EXT_YUV_target"}
vec4 textureProj(samplerExternal2DY2YEXT, vec3);
vec4 textureProj(samplerExternal2DY2YEXT, vec4);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "opSuffix": "Rect", "hasSideEffects": "true", "essl_extension": "ARB_texture_rectangle"}
vec4 textureProj(sampler2DRect, vec3);
vec4 textureProj(sampler2DRect, vec4);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureLod(gsampler2D, vec2, float);
gvec4 textureLod(gsampler3D, vec3, float);
gvec4 textureLod(gsamplerCube, vec3, float);
gvec4 textureLod(gsampler2DArray, vec3, float);
float textureLod(sampler2DShadow, vec3, float);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureLod(gsampler1D, float, float);
float textureLod(sampler1DShadow, vec3, float);
gvec4 textureLod(gsampler1DArray, vec2, float);
float textureLod(sampler1DArrayShadow, vec3, float);
DEFAULT METADATA {"essl_level": "ESSL3_2_BUILTINS", "glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureLod(gsamplerCubeArray, vec4, float);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_texture_cube_map_array, EXT_texture_cube_map_array", "suffix": "Ext"}
gvec4 textureLod(gsamplerCubeArray, vec4, float);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
ivec2 textureSize(gsampler2D, int);
ivec3 textureSize(gsampler3D, int);
ivec2 textureSize(gsamplerCube, int);
ivec3 textureSize(gsampler2DArray, int);
ivec2 textureSize(sampler2DShadow, int);
ivec2 textureSize(samplerCubeShadow, int);
ivec3 textureSize(sampler2DArrayShadow, int);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
int textureSize(gsampler1D, int);
int textureSize(sampler1DShadow, int);
DEFAULT METADATA {"essl_level": "ESSL3_2_BUILTINS", "glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
ivec3 textureSize(gsamplerCubeArray, int);
ivec3 textureSize(samplerCubeArrayShadow, int);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_texture_cube_map_array, EXT_texture_cube_map_array", "suffix": "Ext"}
ivec3 textureSize(gsamplerCubeArray, int);
ivec3 textureSize(samplerCubeArrayShadow, int);
DEFAULT METADATA {"glsl_level": "GLSL1_4_BUILTINS", "hasSideEffects": "true"}
ivec2 textureSize(gsampler2DRect);
ivec2 textureSize(sampler2DRectShadow);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
ivec2 textureSize(gsampler1DArray, int);
ivec2 textureSize(sampler1DArrayShadow, int);
DEFAULT METADATA {"essl_level": "ESSL3_2_BUILTINS", "glsl_level": "GLSL1_4_BUILTINS", "hasSideEffects": "true"}
int textureSize(gsamplerBuffer);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_texture_buffer, EXT_texture_buffer", "suffix": "Ext"}
int textureSize(gsamplerBuffer);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "glsl_level": "GLSL1_5_BUILTINS", "hasSideEffects": "true"}
ivec2 textureSize(gsampler2DMS);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "hasSideEffects": "true", "essl_extension": "ANGLE_texture_multisample", "suffix": "Ext"}
ivec2 textureSize(gsampler2DMS);
DEFAULT METADATA {"glsl_level": "GLSL1_5_BUILTINS", "hasSideEffects": "true"}
ivec3 textureSize(gsampler2DMSArray);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_texture_storage_multisample_2d_array", "suffix": "Ext"}
ivec3 textureSize(gsampler2DMSArray);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_EGL_image_external_essl3"}
ivec2 textureSize(samplerExternalOES, int);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "hasSideEffects": "true", "essl_extension": "EXT_YUV_target"}
ivec2 textureSize(samplerExternal2DY2YEXT, int);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjLod(gsampler2D, vec3, float);
gvec4 textureProjLod(gsampler2D, vec4, float);
gvec4 textureProjLod(gsampler3D, vec4, float);
float textureProjLod(sampler2DShadow, vec4, float);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjLod(gsampler1D, vec2, float);
gvec4 textureProjLod(gsampler1D, vec4, float);
float textureProjLod(sampler1DShadow, vec4, float);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 texelFetch(gsampler2D, ivec2, int);
gvec4 texelFetch(gsampler3D, ivec3, int);
gvec4 texelFetch(gsampler2DArray, ivec3, int);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 texelFetch(gsampler1D, int, int);
DEFAULT METADATA {"glsl_level": "GLSL1_4_BUILTINS", "hasSideEffects": "true"}
gvec4 texelFetch(gsampler2DRect, ivec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 texelFetch(gsampler1DArray, ivec2, int);
DEFAULT METADATA {"essl_level": "ESSL3_2_BUILTINS", "glsl_level": "GLSL1_4_BUILTINS", "hasSideEffects": "true"}
gvec4 texelFetch(gsamplerBuffer, int);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_texture_buffer, EXT_texture_buffer", "suffix": "Ext"}
gvec4 texelFetch(gsamplerBuffer, int);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "glsl_level": "GLSL1_5_BUILTINS", "hasSideEffects": "true"}
gvec4 texelFetch(gsampler2DMS, ivec2, int);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "hasSideEffects": "true", "essl_extension": "ANGLE_texture_multisample", "suffix": "Ext"}
gvec4 texelFetch(gsampler2DMS, ivec2, int);
DEFAULT METADATA {"glsl_level": "GLSL1_5_BUILTINS", "hasSideEffects": "true"}
gvec4 texelFetch(gsampler2DMSArray, ivec3, int);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_texture_storage_multisample_2d_array", "suffix": "Ext"}
gvec4 texelFetch(gsampler2DMSArray, ivec3, int);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_EGL_image_external_essl3"}
vec4 texelFetch(samplerExternalOES, ivec2, int);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "hasSideEffects": "true", "essl_extension": "EXT_YUV_target"}
vec4 texelFetch(samplerExternal2DY2YEXT, ivec2, int);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGrad(gsampler2D, vec2, vec2, vec2);
gvec4 textureGrad(gsampler3D, vec3, vec3, vec3);
gvec4 textureGrad(gsamplerCube, vec3, vec3, vec3);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGrad(gsampler2D, float, float, float);
DEFAULT METADATA {"glsl_level": "GLSL1_4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGrad(gsampler2DRect, vec2, vec2, vec2);
gvec4 textureGrad(sampler2DRectShadow, vec3, vec2, vec2);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
float textureGrad(sampler2DShadow, vec3, vec2, vec2);
float textureGrad(samplerCubeShadow, vec4, vec3, vec3);
gvec4 textureGrad(gsampler2DArray, vec3, vec2, vec2);
float textureGrad(sampler2DArrayShadow, vec4, vec2, vec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
float textureGrad(sampler1DShadow, vec3, float, float);
gvec4 textureGrad(gsampler1DArray, vec2, float, float);
float textureGrad(sampler1DArrayShadow, vec3, float, float);
DEFAULT METADATA {"essl_level": "ESSL3_2_BUILTINS", "glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGrad(gsamplerCubeArray, vec4, vec3, vec3);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_texture_cube_map_array, EXT_texture_cube_map_array", "suffix": "Ext"}
gvec4 textureGrad(gsamplerCubeArray, vec4, vec3, vec3);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjGrad(gsampler2D, vec3, vec2, vec2);
gvec4 textureProjGrad(gsampler2D, vec4, vec2, vec2);
gvec4 textureProjGrad(gsampler3D, vec4, vec3, vec3);
float textureProjGrad(sampler2DShadow, vec4, vec2, vec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjGrad(gsampler1D, vec2, float, float);
gvec4 textureProjGrad(gsampler1D, vec4, float, float);
float textureProjGrad(sampler1DShadow, vec4, float, float);
DEFAULT METADATA {"glsl_level": "GLSL1_4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjGrad(gsampler2DRect, vec3, vec2, vec2);
gvec4 textureProjGrad(gsampler2DRect, vec4, vec2, vec2);
float textureProjGrad(sampler2DRectShadow, vec4, vec2, vec2);
DEFAULT METADATA {"glsl_level": "GLSL4_3_BUILTINS", "hasSideEffects": "true"}
int textureQueryLevels(gsampler1D);
int textureQueryLevels(gsampler2D);
int textureQueryLevels(gsampler3D);
int textureQueryLevels(gsamplerCube);
int textureQueryLevels(gsampler1DArray);
int textureQueryLevels(gsampler2DArray);
int textureQueryLevels(gsamplerCubeArray);
int textureQueryLevels(sampler1DShadow);
int textureQueryLevels(sampler2DShadow);
int textureQueryLevels(samplerCubeShadow);
int textureQueryLevels(sampler1DArrayShadow);
int textureQueryLevels(sampler2DArrayShadow);
int textureQueryLevels(samplerCubeArrayShadow);
DEFAULT METADATA {"glsl_level": "GLSL4_5_BUILTINS", "hasSideEffects": "true"}
int textureSamples(gsampler2DMS);
int textureSamples(gsampler2DMSArray);
GROUP END NoBias
GROUP BEGIN TextureFirstVersionsVS {"shader_type": "VERTEX"}
DEFAULT METADATA {"essl_level": "ESSL1_BUILTINS", "glsl_level": "COMMON_BUILTINS", "hasSideEffects": "true"}
vec4 texture2DLod(sampler2D, vec2, float);
vec4 texture2DProjLod(sampler2D, vec3, float);
vec4 texture2DProjLod(sampler2D, vec4, float);
vec4 textureCubeLod(samplerCube, vec3, float);
DEFAULT METADATA {"glsl_level": "COMMON_BUILTINS", "hasSideEffects": "true"}
vec4 texture1DLod(sampler1D, float, float);
vec4 texture1DProjLod(sampler1D, vec2, float);
vec4 texture1DProjLod(sampler1D, vec4, float);
vec4 shadow1DLod(sampler1DShadow, vec3, float);
vec4 shadow1DProjLod(sampler1DShadow, vec4, float);
vec4 shadow2DLod(sampler2DShadow, vec3, float);
vec4 shadow2DProjLod(sampler2DShadow, vec4, float);
GROUP END TextureFirstVersionsVS
GROUP BEGIN Bias {"shader_type": "FRAGMENT", "opSuffix": "Bias"}
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 texture(gsampler2D, vec2, float);
gvec4 texture(gsampler3D, vec3, float);
gvec4 texture(gsamplerCube, vec3, float);
gvec4 texture(gsampler2DArray, vec3, float);
gvec4 textureProj(gsampler2D, vec3, float);
gvec4 textureProj(gsampler2D, vec4, float);
gvec4 textureProj(gsampler3D, vec4, float);
float texture(sampler2DShadow, vec3, float);
float texture(samplerCubeShadow, vec4, float);
float textureProj(sampler2DShadow, vec4, float);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 texture(gsampler1D, float, float);
float texture(sampler1DShadow, vec3, float);
gvec4 texture(gsampler1DArray, vec3, float);
float texture(sampler1DArrayShadow, vec3, float);
float texture(sampler2DArrayShadow, vec4, float);
gvec4 textureProj(gsampler1D, vec2, float);
gvec4 textureProj(gsampler1D, vec4, float);
float textureProj(sampler1DShadow, vec4, float);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_EGL_image_external_essl3"}
vec4 texture(samplerExternalOES, vec2, float);
vec4 textureProj(samplerExternalOES, vec3, float);
vec4 textureProj(samplerExternalOES, vec4, float);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "hasSideEffects": "true", "essl_extension": "EXT_YUV_target"}
vec4 texture(samplerExternal2DY2YEXT, vec2, float);
vec4 textureProj(samplerExternal2DY2YEXT, vec3, float);
vec4 textureProj(samplerExternal2DY2YEXT, vec4, float);
GROUP END Bias
GROUP BEGIN TextureNoBias
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 texture(gsampler2D, vec2);
gvec4 texture(gsampler3D, vec3);
gvec4 texture(gsamplerCube, vec3);
gvec4 texture(gsampler2DArray, vec3);
float texture(sampler2DShadow, vec3);
float texture(samplerCubeShadow, vec4);
float texture(sampler2DArrayShadow, vec4);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 texture(gsampler1D, float);
float texture(sampler1DShadow, vec3);
gvec4 texture(gsampler1DArray, vec3);
float texture(sampler1DArrayShadow, vec3);
DEFAULT METADATA {"glsl_level": "GLSL1_4_BUILTINS", "hasSideEffects": "true"}
gvec4 texture(gsampler2DRect, vec2);
float texture(sampler2DRectShadow, vec3);
DEFAULT METADATA {"essl_level": "ESSL3_2_BUILTINS", "glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
gvec4 texture(gsamplerCubeArray, vec4);
gvec4 texture(gsamplerCubeArray, vec4, float);
float texture(samplerCubeArrayShadow, vec4, float);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_texture_cube_map_array, EXT_texture_cube_map_array", "suffix": "Ext"}
gvec4 texture(gsamplerCubeArray, vec4);
gvec4 texture(gsamplerCubeArray, vec4, float);
float texture(samplerCubeArrayShadow, vec4, float);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_EGL_image_external_essl3"}
vec4 texture(samplerExternalOES, vec2);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "hasSideEffects": "true", "essl_extension": "EXT_YUV_target"}
vec4 texture(samplerExternal2DY2YEXT, vec2);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProj(gsampler2D, vec3);
gvec4 textureProj(gsampler2D, vec4);
gvec4 textureProj(gsampler3D, vec4);
float textureProj(sampler2DShadow, vec4);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProj(gsampler1D, vec2);
gvec4 textureProj(gsampler1D, vec4);
float textureProj(sampler1DShadow, vec4);
DEFAULT METADATA {"glsl_level": "GLSL1_4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProj(gsampler2DRect, vec3);
gvec4 textureProj(gsampler2DRect, vec4);
float textureProj(sampler2DRectShadow, vec4);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_EGL_image_external_essl3"}
vec4 textureProj(samplerExternalOES, vec3);
vec4 textureProj(samplerExternalOES, vec4);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "hasSideEffects": "true", "essl_extension": "EXT_YUV_target"}
vec4 textureProj(samplerExternal2DY2YEXT, vec3);
vec4 textureProj(samplerExternal2DY2YEXT, vec4);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureLod(gsampler2D, vec2, float);
gvec4 textureLod(gsampler3D, vec3, float);
gvec4 textureLod(gsamplerCube, vec3, float);
gvec4 textureLod(gsampler2DArray, vec3, float);
float textureLod(sampler2DShadow, vec3, float);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureLod(gsampler1D, float, float);
float textureLod(sampler1DShadow, vec3, float);
gvec4 textureLod(gsampler1DArray, vec2, float);
float textureLod(sampler1DArrayShadow, vec3, float);
DEFAULT METADATA {"essl_level": "ESSL3_2_BUILTINS", "glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureLod(gsamplerCubeArray, vec4, float);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_texture_cube_map_array, EXT_texture_cube_map_array", "suffix": "Ext"}
gvec4 textureLod(gsamplerCubeArray, vec4, float);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
ivec2 textureSize(gsampler2D, int);
ivec3 textureSize(gsampler3D, int);
ivec2 textureSize(gsamplerCube, int);
ivec3 textureSize(gsampler2DArray, int);
ivec2 textureSize(sampler2DShadow, int);
ivec2 textureSize(samplerCubeShadow, int);
ivec3 textureSize(sampler2DArrayShadow, int);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
int textureSize(gsampler1D, int);
int textureSize(sampler1DShadow, int);
DEFAULT METADATA {"essl_level": "ESSL3_2_BUILTINS", "glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
ivec3 textureSize(gsamplerCubeArray, int);
ivec3 textureSize(samplerCubeArrayShadow, int);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_texture_cube_map_array, EXT_texture_cube_map_array", "suffix": "Ext"}
ivec3 textureSize(gsamplerCubeArray, int);
ivec3 textureSize(samplerCubeArrayShadow, int);
DEFAULT METADATA {"glsl_level": "GLSL1_4_BUILTINS", "hasSideEffects": "true"}
ivec2 textureSize(gsampler2DRect);
ivec2 textureSize(sampler2DRectShadow);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
ivec2 textureSize(gsampler1DArray, int);
ivec2 textureSize(sampler1DArrayShadow, int);
DEFAULT METADATA {"essl_level": "ESSL3_2_BUILTINS", "glsl_level": "GLSL1_4_BUILTINS", "hasSideEffects": "true"}
int textureSize(gsamplerBuffer);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_texture_buffer, EXT_texture_buffer", "suffix": "Ext"}
int textureSize(gsamplerBuffer);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "glsl_level": "GLSL1_5_BUILTINS", "hasSideEffects": "true"}
ivec2 textureSize(gsampler2DMS);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "hasSideEffects": "true", "essl_extension": "ANGLE_texture_multisample", "suffix": "Ext"}
ivec2 textureSize(gsampler2DMS);
DEFAULT METADATA {"glsl_level": "GLSL1_5_BUILTINS", "hasSideEffects": "true"}
ivec3 textureSize(gsampler2DMSArray);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_texture_storage_multisample_2d_array", "suffix": "Ext"}
ivec3 textureSize(gsampler2DMSArray);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_EGL_image_external_essl3"}
ivec2 textureSize(samplerExternalOES, int);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "hasSideEffects": "true", "essl_extension": "EXT_YUV_target"}
ivec2 textureSize(samplerExternal2DY2YEXT, int);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjLod(gsampler2D, vec3, float);
gvec4 textureProjLod(gsampler2D, vec4, float);
gvec4 textureProjLod(gsampler3D, vec4, float);
float textureProjLod(sampler2DShadow, vec4, float);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjLod(gsampler1D, vec2, float);
gvec4 textureProjLod(gsampler1D, vec4, float);
float textureProjLod(sampler1DShadow, vec4, float);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 texelFetch(gsampler2D, ivec2, int);
gvec4 texelFetch(gsampler3D, ivec3, int);
gvec4 texelFetch(gsampler2DArray, ivec3, int);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 texelFetch(gsampler1D, int, int);
DEFAULT METADATA {"glsl_level": "GLSL1_4_BUILTINS", "hasSideEffects": "true"}
gvec4 texelFetch(gsampler2DRect, ivec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 texelFetch(gsampler1DArray, ivec2, int);
DEFAULT METADATA {"essl_level": "ESSL3_2_BUILTINS", "glsl_level": "GLSL1_4_BUILTINS", "hasSideEffects": "true"}
gvec4 texelFetch(gsamplerBuffer, int);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_texture_buffer, EXT_texture_buffer", "suffix": "Ext"}
gvec4 texelFetch(gsamplerBuffer, int);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "glsl_level": "GLSL1_5_BUILTINS", "hasSideEffects": "true"}
gvec4 texelFetch(gsampler2DMS, ivec2, int);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "hasSideEffects": "true", "essl_extension": "ANGLE_texture_multisample", "suffix": "Ext"}
gvec4 texelFetch(gsampler2DMS, ivec2, int);
DEFAULT METADATA {"glsl_level": "GLSL1_5_BUILTINS", "hasSideEffects": "true"}
gvec4 texelFetch(gsampler2DMSArray, ivec3, int);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_texture_storage_multisample_2d_array", "suffix": "Ext"}
gvec4 texelFetch(gsampler2DMSArray, ivec3, int);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_EGL_image_external_essl3"}
vec4 texelFetch(samplerExternalOES, ivec2, int);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "hasSideEffects": "true", "essl_extension": "EXT_YUV_target"}
vec4 texelFetch(samplerExternal2DY2YEXT, ivec2, int);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGrad(gsampler2D, vec2, vec2, vec2);
gvec4 textureGrad(gsampler3D, vec3, vec3, vec3);
gvec4 textureGrad(gsamplerCube, vec3, vec3, vec3);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGrad(gsampler2D, float, float, float);
DEFAULT METADATA {"glsl_level": "GLSL1_4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGrad(gsampler2DRect, vec2, vec2, vec2);
gvec4 textureGrad(sampler2DRectShadow, vec3, vec2, vec2);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
float textureGrad(sampler2DShadow, vec3, vec2, vec2);
float textureGrad(samplerCubeShadow, vec4, vec3, vec3);
gvec4 textureGrad(gsampler2DArray, vec3, vec2, vec2);
float textureGrad(sampler2DArrayShadow, vec4, vec2, vec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
float textureGrad(sampler1DShadow, vec3, float, float);
gvec4 textureGrad(gsampler1DArray, vec2, float, float);
float textureGrad(sampler1DArrayShadow, vec3, float, float);
DEFAULT METADATA {"essl_level": "ESSL3_2_BUILTINS", "glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGrad(gsamplerCubeArray, vec4, vec3, vec3);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_texture_cube_map_array, EXT_texture_cube_map_array", "suffix": "Ext"}
gvec4 textureGrad(gsamplerCubeArray, vec4, vec3, vec3);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjGrad(gsampler2D, vec3, vec2, vec2);
gvec4 textureProjGrad(gsampler2D, vec4, vec2, vec2);
gvec4 textureProjGrad(gsampler3D, vec4, vec3, vec3);
float textureProjGrad(sampler2DShadow, vec4, vec2, vec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjGrad(gsampler1D, vec2, float, float);
gvec4 textureProjGrad(gsampler1D, vec4, float, float);
float textureProjGrad(sampler1DShadow, vec4, float, float);
DEFAULT METADATA {"glsl_level": "GLSL1_4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjGrad(gsampler2DRect, vec3, vec2, vec2);
gvec4 textureProjGrad(gsampler2DRect, vec4, vec2, vec2);
float textureProjGrad(sampler2DRectShadow, vec4, vec2, vec2);
DEFAULT METADATA {"glsl_level": "GLSL4_3_BUILTINS", "hasSideEffects": "true"}
int textureQueryLevels(gsampler1D);
int textureQueryLevels(gsampler2D);
int textureQueryLevels(gsampler3D);
int textureQueryLevels(gsamplerCube);
int textureQueryLevels(gsampler1DArray);
int textureQueryLevels(gsampler2DArray);
int textureQueryLevels(gsamplerCubeArray);
int textureQueryLevels(sampler1DShadow);
int textureQueryLevels(sampler2DShadow);
int textureQueryLevels(samplerCubeShadow);
int textureQueryLevels(sampler1DArrayShadow);
int textureQueryLevels(sampler2DArrayShadow);
int textureQueryLevels(samplerCubeArrayShadow);
DEFAULT METADATA {"glsl_level": "GLSL4_5_BUILTINS", "hasSideEffects": "true"}
int textureSamples(gsampler2DMS);
int textureSamples(gsampler2DMSArray);
GROUP END TextureNoBias
GROUP BEGIN QueryLod {"shader_type": "FRAGMENT"}
DEFAULT METADATA {"glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
vec2 textureQueryLod(gsampler1D, float);
vec2 textureQueryLod(gsampler2D, vec2);
vec2 textureQueryLod(gsampler3D, vec3);
vec2 textureQueryLod(gsamplerCube, vec3);
vec2 textureQueryLod(gsampler1DArray, float);
vec2 textureQueryLod(gsampler2DArray, vec2);
vec2 textureQueryLod(gsamplerCubeArray, vec3);
vec2 textureQueryLod(sampler1DShadow, float);
vec2 textureQueryLod(sampler2DShadow, vec2);
vec2 textureQueryLod(samplerCubeShadow, vec3);
vec2 textureQueryLod(sampler1DArrayShadow, float);
vec2 textureQueryLod(sampler2DArrayShadow, vec2);
vec2 textureQueryLod(samplerCubeArrayShadow, vec3);
GROUP END QueryLod
GROUP BEGIN TextureBias {"shader_type": "FRAGMENT", "opSuffix": "Bias"}
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 texture(gsampler2D, vec2, float);
gvec4 texture(gsampler3D, vec3, float);
gvec4 texture(gsamplerCube, vec3, float);
gvec4 texture(gsampler2DArray, vec3, float);
gvec4 textureProj(gsampler2D, vec3, float);
gvec4 textureProj(gsampler2D, vec4, float);
gvec4 textureProj(gsampler3D, vec4, float);
float texture(sampler2DShadow, vec3, float);
float texture(samplerCubeShadow, vec4, float);
float textureProj(sampler2DShadow, vec4, float);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 texture(gsampler1D, float, float);
float texture(sampler1DShadow, vec3, float);
gvec4 texture(gsampler1DArray, vec3, float);
float texture(sampler1DArrayShadow, vec3, float);
float texture(sampler2DArrayShadow, vec4, float);
gvec4 textureProj(gsampler1D, vec2, float);
gvec4 textureProj(gsampler1D, vec4, float);
float textureProj(sampler1DShadow, vec4, float);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_EGL_image_external_essl3"}
vec4 texture(samplerExternalOES, vec2, float);
vec4 textureProj(samplerExternalOES, vec3, float);
vec4 textureProj(samplerExternalOES, vec4, float);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "hasSideEffects": "true", "essl_extension": "EXT_YUV_target"}
vec4 texture(samplerExternal2DY2YEXT, vec2, float);
vec4 textureProj(samplerExternal2DY2YEXT, vec3, float);
vec4 textureProj(samplerExternal2DY2YEXT, vec4, float);
GROUP END TextureBias
GROUP BEGIN OffsetNoBias {"queryFunction": true}
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureOffset(gsampler2D, vec2, ivec2);
gvec4 textureOffset(gsampler3D, vec3, ivec3);
float textureOffset(sampler2DShadow, vec3, ivec2);
gvec4 textureOffset(gsampler2DArray, vec3, ivec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureOffset(gsampler1D, float, int);
DEFAULT METADATA {"glsl_level": "GLSL1_4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureOffset(gsampler2DRect, vec2, ivec2);
float textureOffset(sampler2DRectShadow, vec3, ivec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
float textureOffset(sampler1DShadow, vec3, int);
gvec4 textureOffset(gsampler1DArray, vec2, int);
float textureOffset(sampler1DArrayShadow, vec3, int);
DEFAULT METADATA {"glsl_level": "GLSL4_3_BUILTINS", "hasSideEffects": "true"}
float textureOffset(sampler2DArrayShadow, vec4, ivec2);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjOffset(gsampler2D, vec3, ivec2);
gvec4 textureProjOffset(gsampler2D, vec4, ivec2);
gvec4 textureProjOffset(gsampler3D, vec4, ivec3);
float textureProjOffset(sampler2DShadow, vec4, ivec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjOffset(gsampler1D, vec2, int);
gvec4 textureProjOffset(gsampler1D, vec4, int);
DEFAULT METADATA {"glsl_level": "GLSL1_4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjOffset(gsampler2DRect, vec3, ivec2);
gvec4 textureProjOffset(gsampler2DRect, vec4, ivec2);
float textureProjOffset(sampler2DRectShadow, vec4, ivec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
float textureProjOffset(sampler1DShadow, vec4, int);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureLodOffset(gsampler2D, vec2, float, ivec2);
gvec4 textureLodOffset(gsampler3D, vec3, float, ivec3);
float textureLodOffset(sampler2DShadow, vec3, float, ivec2);
gvec4 textureLodOffset(gsampler2DArray, vec3, float, ivec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureLodOffset(gsampler1D, float, float, int);
float textureLodOffset(sampler1DShadow, vec3, float, int);
gvec4 textureLodOffset(gsampler1DArray, vec2, float, int);
float textureLodOffset(sampler1DArrayShadow, vec3, float, int);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjLodOffset(gsampler2D, vec3, float, ivec2);
gvec4 textureProjLodOffset(gsampler2D, vec4, float, ivec2);
gvec4 textureProjLodOffset(gsampler3D, vec4, float, ivec3);
float textureProjLodOffset(sampler2DShadow, vec4, float, ivec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjLodOffset(gsampler1D, vec2, float, int);
gvec4 textureProjLodOffset(gsampler1D, vec4, float, int);
float textureProjLodOffset(sampler1DShadow, vec4, float, int);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 texelFetchOffset(gsampler2D, ivec2, int, ivec2);
gvec4 texelFetchOffset(gsampler3D, ivec3, int, ivec3);
gvec4 texelFetchOffset(gsampler2DArray, ivec3, int, ivec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 texelFetchOffset(gsampler1D, int, int, int);
DEFAULT METADATA {"glsl_level": "GLSL1_4_BUILTINS", "hasSideEffects": "true"}
gvec4 texelFetchOffset(gsampler2DRect, ivec2, ivec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 texelFetchOffset(gsampler1DArray, ivec2, int, int);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGradOffset(gsampler2D, vec2, vec2, vec2, ivec2);
gvec4 textureGradOffset(gsampler3D, vec3, vec3, vec3, ivec3);
float textureGradOffset(sampler2DShadow, vec3, vec2, vec2, ivec2);
gvec4 textureGradOffset(gsampler2DArray, vec3, vec2, vec2, ivec2);
float textureGradOffset(sampler2DArrayShadow, vec4, vec2, vec2, ivec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGradOffset(gsampler1D, float, float, float, int);
DEFAULT METADATA {"glsl_level": "GLSL1_4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGradOffset(gsampler2DRect, vec2, vec2, vec2, ivec2);
float textureGradOffset(sampler2DRectShadow, vec3, vec2, vec2, ivec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
float textureGradOffset(sampler1DShadow, vec3, float, float, int);
gvec4 textureGradOffset(gsampler1DArray, vec2, float, float, int);
float textureGradOffset(sampler1DArrayShadow, vec3, float, float, int);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjGradOffset(gsampler2D, vec3, vec2, vec2, ivec2);
gvec4 textureProjGradOffset(gsampler2D, vec4, vec2, vec2, ivec2);
gvec4 textureProjGradOffset(gsampler3D, vec4, vec3, vec3, ivec3);
float textureProjGradOffset(sampler2DShadow, vec4, vec2, vec2, ivec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjGradOffset(gsampler1D, vec2, float, float, int);
gvec4 textureProjGradOffset(gsampler1D, vec4, float, float, int);
DEFAULT METADATA {"glsl_level": "GLSL1_4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjGradOffset(gsampler2DRect, vec3, vec2, vec2, ivec2);
gvec4 textureProjGradOffset(gsampler2DRect, vec4, vec2, vec2, ivec2);
float textureProjGradOffset(sampler2DRectShadow, vec4, vec2, vec2, ivec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
float textureProjGradOffset(sampler1DShadow, vec4, float, float, int);
GROUP END OffsetNoBias
GROUP BEGIN TextureQueryLod {"shader_type": "FRAGMENT"}
DEFAULT METADATA {"glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
vec2 textureQueryLod(gsampler1D, float);
vec2 textureQueryLod(gsampler2D, vec2);
vec2 textureQueryLod(gsampler3D, vec3);
vec2 textureQueryLod(gsamplerCube, vec3);
vec2 textureQueryLod(gsampler1DArray, float);
vec2 textureQueryLod(gsampler2DArray, vec2);
vec2 textureQueryLod(gsamplerCubeArray, vec3);
vec2 textureQueryLod(sampler1DShadow, float);
vec2 textureQueryLod(sampler2DShadow, vec2);
vec2 textureQueryLod(samplerCubeShadow, vec3);
vec2 textureQueryLod(sampler1DArrayShadow, float);
vec2 textureQueryLod(sampler2DArrayShadow, vec2);
vec2 textureQueryLod(samplerCubeArrayShadow, vec3);
GROUP END TextureQueryLod
GROUP BEGIN OffsetBias {"queryFunction": true, "shader_type": "FRAGMENT", "opSuffix": "Bias"}
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureOffset(gsampler2D, vec2, ivec2, float);
gvec4 textureOffset(gsampler3D, vec3, ivec3, float);
float textureOffset(sampler2DShadow, vec3, ivec2, float);
gvec4 textureOffset(gsampler2DArray, vec3, ivec2, float);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureOffset(gsampler1D, float, int, float);
float textureOffset(sampler1DShadow, vec3, int, float);
gvec4 textureOffset(gsampler1DArray, vec2, int, float);
float textureOffset(sampler1DArrayShadow, vec3, int, float);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjOffset(gsampler2D, vec3, ivec2, float);
gvec4 textureProjOffset(gsampler2D, vec4, ivec2, float);
gvec4 textureProjOffset(gsampler3D, vec4, ivec3, float);
float textureProjOffset(sampler2DShadow, vec4, ivec2, float);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjOffset(gsampler1D, vec2, int, float);
gvec4 textureProjOffset(gsampler1D, vec4, int, float);
float textureProjOffset(sampler1DShadow, vec4, int, float);
GROUP END OffsetBias
GROUP BEGIN TextureOffsetNoBias {"queryFunction": true}
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureOffset(gsampler2D, vec2, ivec2);
gvec4 textureOffset(gsampler3D, vec3, ivec3);
float textureOffset(sampler2DShadow, vec3, ivec2);
gvec4 textureOffset(gsampler2DArray, vec3, ivec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureOffset(gsampler1D, float, int);
DEFAULT METADATA {"glsl_level": "GLSL1_4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureOffset(gsampler2DRect, vec2, ivec2);
float textureOffset(sampler2DRectShadow, vec3, ivec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
float textureOffset(sampler1DShadow, vec3, int);
gvec4 textureOffset(gsampler1DArray, vec2, int);
float textureOffset(sampler1DArrayShadow, vec3, int);
DEFAULT METADATA {"glsl_level": "GLSL4_3_BUILTINS", "hasSideEffects": "true"}
float textureOffset(sampler2DArrayShadow, vec4, ivec2);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjOffset(gsampler2D, vec3, ivec2);
gvec4 textureProjOffset(gsampler2D, vec4, ivec2);
gvec4 textureProjOffset(gsampler3D, vec4, ivec3);
float textureProjOffset(sampler2DShadow, vec4, ivec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjOffset(gsampler1D, vec2, int);
gvec4 textureProjOffset(gsampler1D, vec4, int);
DEFAULT METADATA {"glsl_level": "GLSL1_4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjOffset(gsampler2DRect, vec3, ivec2);
gvec4 textureProjOffset(gsampler2DRect, vec4, ivec2);
float textureProjOffset(sampler2DRectShadow, vec4, ivec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
float textureProjOffset(sampler1DShadow, vec4, int);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureLodOffset(gsampler2D, vec2, float, ivec2);
gvec4 textureLodOffset(gsampler3D, vec3, float, ivec3);
float textureLodOffset(sampler2DShadow, vec3, float, ivec2);
gvec4 textureLodOffset(gsampler2DArray, vec3, float, ivec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureLodOffset(gsampler1D, float, float, int);
float textureLodOffset(sampler1DShadow, vec3, float, int);
gvec4 textureLodOffset(gsampler1DArray, vec2, float, int);
float textureLodOffset(sampler1DArrayShadow, vec3, float, int);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjLodOffset(gsampler2D, vec3, float, ivec2);
gvec4 textureProjLodOffset(gsampler2D, vec4, float, ivec2);
gvec4 textureProjLodOffset(gsampler3D, vec4, float, ivec3);
float textureProjLodOffset(sampler2DShadow, vec4, float, ivec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjLodOffset(gsampler1D, vec2, float, int);
gvec4 textureProjLodOffset(gsampler1D, vec4, float, int);
float textureProjLodOffset(sampler1DShadow, vec4, float, int);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 texelFetchOffset(gsampler2D, ivec2, int, ivec2);
gvec4 texelFetchOffset(gsampler3D, ivec3, int, ivec3);
gvec4 texelFetchOffset(gsampler2DArray, ivec3, int, ivec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 texelFetchOffset(gsampler1D, int, int, int);
DEFAULT METADATA {"glsl_level": "GLSL1_4_BUILTINS", "hasSideEffects": "true"}
gvec4 texelFetchOffset(gsampler2DRect, ivec2, ivec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 texelFetchOffset(gsampler1DArray, ivec2, int, int);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGradOffset(gsampler2D, vec2, vec2, vec2, ivec2);
gvec4 textureGradOffset(gsampler3D, vec3, vec3, vec3, ivec3);
float textureGradOffset(sampler2DShadow, vec3, vec2, vec2, ivec2);
gvec4 textureGradOffset(gsampler2DArray, vec3, vec2, vec2, ivec2);
float textureGradOffset(sampler2DArrayShadow, vec4, vec2, vec2, ivec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGradOffset(gsampler1D, float, float, float, int);
DEFAULT METADATA {"glsl_level": "GLSL1_4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGradOffset(gsampler2DRect, vec2, vec2, vec2, ivec2);
float textureGradOffset(sampler2DRectShadow, vec3, vec2, vec2, ivec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
float textureGradOffset(sampler1DShadow, vec3, float, float, int);
gvec4 textureGradOffset(gsampler1DArray, vec2, float, float, int);
float textureGradOffset(sampler1DArrayShadow, vec3, float, float, int);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjGradOffset(gsampler2D, vec3, vec2, vec2, ivec2);
gvec4 textureProjGradOffset(gsampler2D, vec4, vec2, vec2, ivec2);
gvec4 textureProjGradOffset(gsampler3D, vec4, vec3, vec3, ivec3);
float textureProjGradOffset(sampler2DShadow, vec4, vec2, vec2, ivec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjGradOffset(gsampler1D, vec2, float, float, int);
gvec4 textureProjGradOffset(gsampler1D, vec4, float, float, int);
DEFAULT METADATA {"glsl_level": "GLSL1_4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjGradOffset(gsampler2DRect, vec3, vec2, vec2, ivec2);
gvec4 textureProjGradOffset(gsampler2DRect, vec4, vec2, vec2, ivec2);
float textureProjGradOffset(sampler2DRectShadow, vec4, vec2, vec2, ivec2);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
float textureProjGradOffset(sampler1DShadow, vec4, float, float, int);
GROUP END TextureOffsetNoBias
GROUP BEGIN Gather {"queryFunction": true}
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGather(gsampler2D, vec2);
gvec4 textureGather(gsampler2D, vec2, int);
gvec4 textureGather(gsampler2DArray, vec3);
gvec4 textureGather(gsampler2DArray, vec3, int);
gvec4 textureGather(gsamplerCube, vec3);
gvec4 textureGather(gsamplerCube, vec3, int);
DEFAULT METADATA {"essl_level": "ESSL3_2_BUILTINS", "glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGather(gsamplerCubeArray, vec4);
gvec4 textureGather(gsamplerCubeArray, vec4, int);
vec4 textureGather(samplerCubeArrayShadow, vec4, float);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_texture_cube_map_array, EXT_texture_cube_map_array", "suffix": "Ext"}
gvec4 textureGather(gsamplerCubeArray, vec4);
gvec4 textureGather(gsamplerCubeArray, vec4, int);
vec4 textureGather(samplerCubeArrayShadow, vec4, float);
DEFAULT METADATA {"glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGather(gsampler2DRect, vec3);
gvec4 textureGather(gsampler2DRect, vec3, int);
vec4 textureGather(sampler2DRectShadow, vec2, float);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "hasSideEffects": "true"}
vec4 textureGather(sampler2DShadow, vec2);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
vec4 textureGather(sampler2DShadow, vec2, float);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "hasSideEffects": "true"}
vec4 textureGather(sampler2DArrayShadow, vec3);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
vec4 textureGather(sampler2DArrayShadow, vec3, float);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "hasSideEffects": "true"}
vec4 textureGather(samplerCubeShadow, vec3);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
vec4 textureGather(samplerCubeShadow, vec3, float);
GROUP BEGIN TextureOffsetBias {"queryFunction": true, "shader_type": "FRAGMENT", "opSuffix": "Bias"}
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureOffset(gsampler2D, vec2, ivec2, float);
gvec4 textureOffset(gsampler3D, vec3, ivec3, float);
float textureOffset(sampler2DShadow, vec3, ivec2, float);
gvec4 textureOffset(gsampler2DArray, vec3, ivec2, float);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureOffset(gsampler1D, float, int, float);
float textureOffset(sampler1DShadow, vec3, int, float);
gvec4 textureOffset(gsampler1DArray, vec2, int, float);
float textureOffset(sampler1DArrayShadow, vec3, int, float);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjOffset(gsampler2D, vec3, ivec2, float);
gvec4 textureProjOffset(gsampler2D, vec4, ivec2, float);
gvec4 textureProjOffset(gsampler3D, vec4, ivec3, float);
float textureProjOffset(sampler2DShadow, vec4, ivec2, float);
DEFAULT METADATA {"glsl_level": "GLSL1_3_BUILTINS", "hasSideEffects": "true"}
gvec4 textureProjOffset(gsampler1D, vec2, int, float);
gvec4 textureProjOffset(gsampler1D, vec4, int, float);
float textureProjOffset(sampler1DShadow, vec4, int, float);
GROUP END TextureOffsetBias
GROUP BEGIN Offset {"queryFunction": true}
GROUP BEGIN NoComp {"queryFunction": true}
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGatherOffset(gsampler2D, vec2, ivec2);
gvec4 textureGatherOffset(gsampler2DArray, vec3, ivec2);
vec4 textureGatherOffset(sampler2DShadow, vec2, float, ivec2);
vec4 textureGatherOffset(sampler2DArrayShadow, vec3, float, ivec2);
DEFAULT METADATA {"glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGatherOffset(gsampler2DRect, vec2, ivec2);
vec4 textureGatherOffset(sampler2DRectShadow, vec2, float, ivec2);
GROUP END NoComp
GROUP BEGIN Comp {"queryFunction": true, "opSuffix": "Comp"}
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGatherOffset(gsampler2D, vec2, ivec2, int);
gvec4 textureGatherOffset(gsampler2DArray, vec3, ivec2, int);
DEFAULT METADATA {"glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGatherOffset(gsampler2DRect, vec2, ivec2, int);
GROUP END Comp
GROUP END Offset
GROUP BEGIN Offsets {"queryFunction": true}
GROUP BEGIN NoComp {"queryFunction": true}
DEFAULT METADATA {"essl_level": "ESSL3_2_BUILTINS", "glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGatherOffsets(gsampler2D, vec2, ivec2[4]);
gvec4 textureGatherOffsets(gsampler2DArray, vec3, ivec2[4]);
vec4 textureGatherOffsets(sampler2DShadow, vec2, float, ivec2[4]);
vec4 textureGatherOffsets(sampler2DArrayShadow, vec3, float, ivec2[4]);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "hasSideEffects": "true", "essl_extension": "EXT_gpu_shader5", "suffix": "Ext"}
gvec4 textureGatherOffsets(gsampler2D, vec2, ivec2[4]);
gvec4 textureGatherOffsets(gsampler2DArray, vec3, ivec2[4]);
vec4 textureGatherOffsets(sampler2DShadow, vec2, float, ivec2[4]);
vec4 textureGatherOffsets(sampler2DArrayShadow, vec3, float, ivec2[4]);
DEFAULT METADATA {"glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGatherOffsets(gsampler2DRect, vec2, ivec2[4]);
vec4 textureGatherOffsets(sampler2DRectShadow, vec2, float, ivec2[4]);
GROUP END NoComp
GROUP BEGIN Comp {"queryFunction": true, "opSuffix": "Comp"}
DEFAULT METADATA {"essl_level": "ESSL3_2_BUILTINS", "glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGatherOffsets(gsampler2D, vec2, ivec2[4], int);
gvec4 textureGatherOffsets(gsampler2DArray, vec3, ivec2[4], int);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "hasSideEffects": "true", "essl_extension": "EXT_gpu_shader5", "suffix": "Ext"}
gvec4 textureGatherOffsets(gsampler2D, vec2, ivec2[4], int);
gvec4 textureGatherOffsets(gsampler2DArray, vec3, ivec2[4], int);
DEFAULT METADATA {"glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGatherOffsets(gsampler2DRect, vec2, ivec2[4], int);
GROUP END Comp
GROUP END Offsets
GROUP END Gather
GROUP END Texture
GROUP BEGIN EXT_yuv_target
GROUP BEGIN EXT_YUV_target
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "hasSideEffects": "true", "essl_extension": "EXT_YUV_target"}
vec3 rgb_2_yuv(vec3, yuvCscStandardEXT);
vec3 yuv_2_rgb(vec3, yuvCscStandardEXT);
GROUP END EXT_yuv_target
GROUP BEGIN TextureGather {"queryFunction": true}
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGather(gsampler2D, vec2);
gvec4 textureGather(gsampler2D, vec2, int);
gvec4 textureGather(gsampler2DArray, vec3);
gvec4 textureGather(gsampler2DArray, vec3, int);
gvec4 textureGather(gsamplerCube, vec3);
gvec4 textureGather(gsamplerCube, vec3, int);
DEFAULT METADATA {"essl_level": "ESSL3_2_BUILTINS", "glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGather(gsamplerCubeArray, vec4);
gvec4 textureGather(gsamplerCubeArray, vec4, int);
vec4 textureGather(samplerCubeArrayShadow, vec4, float);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "hasSideEffects": "true", "essl_extension": "OES_texture_cube_map_array, EXT_texture_cube_map_array", "suffix": "Ext"}
gvec4 textureGather(gsamplerCubeArray, vec4);
gvec4 textureGather(gsamplerCubeArray, vec4, int);
vec4 textureGather(samplerCubeArrayShadow, vec4, float);
DEFAULT METADATA {"glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGather(gsampler2DRect, vec3);
gvec4 textureGather(gsampler2DRect, vec3, int);
vec4 textureGather(sampler2DRectShadow, vec2, float);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "hasSideEffects": "true"}
vec4 textureGather(sampler2DShadow, vec2);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
vec4 textureGather(sampler2DShadow, vec2, float);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "hasSideEffects": "true"}
vec4 textureGather(sampler2DArrayShadow, vec3);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
vec4 textureGather(sampler2DArrayShadow, vec3, float);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "hasSideEffects": "true"}
vec4 textureGather(samplerCubeShadow, vec3);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
vec4 textureGather(samplerCubeShadow, vec3, float);
GROUP BEGIN Offset {"queryFunction": true}
GROUP BEGIN NoComp {"queryFunction": true}
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGatherOffset(gsampler2D, vec2, ivec2);
gvec4 textureGatherOffset(gsampler2DArray, vec3, ivec2);
vec4 textureGatherOffset(sampler2DShadow, vec2, float, ivec2);
vec4 textureGatherOffset(sampler2DArrayShadow, vec3, float, ivec2);
DEFAULT METADATA {"glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGatherOffset(gsampler2DRect, vec2, ivec2);
vec4 textureGatherOffset(sampler2DRectShadow, vec2, float, ivec2);
GROUP END NoComp
GROUP BEGIN Comp {"queryFunction": true, "opSuffix": "Comp"}
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGatherOffset(gsampler2D, vec2, ivec2, int);
gvec4 textureGatherOffset(gsampler2DArray, vec3, ivec2, int);
DEFAULT METADATA {"glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGatherOffset(gsampler2DRect, vec2, ivec2, int);
GROUP END Comp
GROUP END Offset
GROUP BEGIN Offsets {"queryFunction": true}
GROUP BEGIN NoComp {"queryFunction": true}
DEFAULT METADATA {"essl_level": "ESSL3_2_BUILTINS", "glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGatherOffsets(gsampler2D, vec2, ivec2[4]);
gvec4 textureGatherOffsets(gsampler2DArray, vec3, ivec2[4]);
vec4 textureGatherOffsets(sampler2DShadow, vec2, float, ivec2[4]);
vec4 textureGatherOffsets(sampler2DArrayShadow, vec3, float, ivec2[4]);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "hasSideEffects": "true", "essl_extension": "EXT_gpu_shader5", "suffix": "Ext"}
gvec4 textureGatherOffsets(gsampler2D, vec2, ivec2[4]);
gvec4 textureGatherOffsets(gsampler2DArray, vec3, ivec2[4]);
vec4 textureGatherOffsets(sampler2DShadow, vec2, float, ivec2[4]);
vec4 textureGatherOffsets(sampler2DArrayShadow, vec3, float, ivec2[4]);
DEFAULT METADATA {"glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGatherOffsets(gsampler2DRect, vec2, ivec2[4]);
vec4 textureGatherOffsets(sampler2DRectShadow, vec2, float, ivec2[4]);
GROUP END NoComp
GROUP BEGIN Comp {"queryFunction": true, "opSuffix": "Comp"}
DEFAULT METADATA {"essl_level": "ESSL3_2_BUILTINS", "glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGatherOffsets(gsampler2D, vec2, ivec2[4], int);
gvec4 textureGatherOffsets(gsampler2DArray, vec3, ivec2[4], int);
DEFAULT METADATA {"essl_level": "ESSL3_1_BUILTINS", "hasSideEffects": "true", "essl_extension": "EXT_gpu_shader5", "suffix": "Ext"}
gvec4 textureGatherOffsets(gsampler2D, vec2, ivec2[4], int);
gvec4 textureGatherOffsets(gsampler2DArray, vec3, ivec2[4], int);
DEFAULT METADATA {"glsl_level": "GLSL4_BUILTINS", "hasSideEffects": "true"}
gvec4 textureGatherOffsets(gsampler2DRect, vec2, ivec2[4], int);
GROUP END Comp
GROUP END Offsets
GROUP END TextureGather
GROUP END EXT_YUV_target
GROUP BEGIN DerivativesFS {"shader_type": "FRAGMENT"}
DEFAULT METADATA {"essl_level": "ESSL1_BUILTINS", "essl_extension": "OES_standard_derivatives", "hasSideEffects": "true", "suffix": "Ext"}
......@@ -1084,6 +1085,7 @@ GROUP BEGIN Image {"queryFunction": true}
DEFAULT METADATA {"glsl_level": "GLSL4_5_BUILTINS", "hasSideEffects": "true"}
int imageSamples(readonly writeonly gimage2DMS);
int imageSamples(readonly writeonly gimage2DMSArray);
GROUP BEGIN Atomic {"queryFunction": true}
DEFAULT METADATA {"glsl_level": "GLSL4_2_BUILTINS", "hasSideEffects": "true"}
uint imageAtomicAdd(IMAGE_PARAMS, uint);
......@@ -1180,10 +1182,3 @@ GROUP BEGIN ShaderInvocationGroup
bool allInvocations(bool);
bool allInvocationsEqual(bool);
GROUP END ShaderInvocationGroup
GROUP BEGIN WEBGLVideoTexture
DEFAULT METADATA {"essl_level": "ESSL1_BUILTINS", "glsl_level": "COMMON_BUILTINS", "hasSideEffects": "true", "extension": "WEBGL_video_texture"}
vec4 textureVideoWEBGL(samplerVideoWEBGL, vec2);
DEFAULT METADATA {"essl_level": "ESSL3_BUILTINS", "glsl_level": "GLSL1_3_BUILTINS", "opSuffix": "VideoWEBGL", "hasSideEffects": "true", "extension": "WEBGL_video_texture"}
vec4 texture(samplerVideoWEBGL, vec2);
GROUP END WEBGLVideoTexture
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -1981,7 +1981,8 @@ angle::Result GraphicsPipelineDesc::initializePipeline(
if (contextVk->getFeatures().supportsTransformFeedbackExtension.enabled)
{
rasterStreamState.rasterizationStream = 0;
rasterState.pNext = &rasterLineState;
*pNextPtr = &rasterStreamState;
pNextPtr = &rasterStreamState.pNext;
}
// Multisample state.
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment