HLSL: Add better diagnostic when using in/out qualifiers in global scope (#2258)
[platform/upstream/glslang.git] / hlsl / hlslParseables.cpp
1 //
2 // Copyright (C) 2016 LunarG, Inc.
3 //
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions
8 // are met:
9 //
10 //    Redistributions of source code must retain the above copyright
11 //    notice, this list of conditions and the following disclaimer.
12 //
13 //    Redistributions in binary form must reproduce the above
14 //    copyright notice, this list of conditions and the following
15 //    disclaimer in the documentation and/or other materials provided
16 //    with the distribution.
17 //
18 //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
19 //    contributors may be used to endorse or promote products derived
20 //    from this software without specific prior written permission.
21 //
22 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 // POSSIBILITY OF SUCH DAMAGE.
34 //
35
36 //
37 // Create strings that declare built-in definitions, add built-ins programmatically
38 // that cannot be expressed in the strings, and establish mappings between
39 // built-in functions and operators.
40 //
41 // Where to put a built-in:
42 //   TBuiltInParseablesHlsl::initialize(version,profile) context-independent textual built-ins; add them to the right string
43 //   TBuiltInParseablesHlsl::initialize(resources,...)   context-dependent textual built-ins; add them to the right string
44 //   TBuiltInParseablesHlsl::identifyBuiltIns(...,symbolTable) context-independent programmatic additions/mappings to the symbol table,
45 //                                                including identifying what extensions are needed if a version does not allow a symbol
46 //   TBuiltInParseablesHlsl::identifyBuiltIns(...,symbolTable, resources) context-dependent programmatic additions/mappings to the
47 //                                                symbol table, including identifying what extensions are needed if a version does
48 //                                                not allow a symbol
49 //
50
51 #include "hlslParseables.h"
52 #include "hlslParseHelper.h"
53 #include <cctype>
54 #include <utility>
55 #include <algorithm>
56
57 namespace {  // anonymous namespace functions
58
59 const bool UseHlslTypes = true;
60
61 const char* BaseTypeName(const char argOrder, const char* scalarName, const char* vecName, const char* matName)
62 {
63     switch (argOrder) {
64     case 'S': return scalarName;
65     case 'V': return vecName;
66     case 'M': return matName;
67     default:  return "UNKNOWN_TYPE";
68     }
69 }
70
71 // arg order queries
72 bool IsSamplerType(const char argType)     { return argType == 'S' || argType == 's'; }
73 bool IsArrayed(const char argOrder)        { return argOrder == '@' || argOrder == '&' || argOrder == '#'; }
74 bool IsTextureNonMS(const char argOrder)   { return argOrder == '%'; }
75 bool IsSubpassInput(const char argOrder)   { return argOrder == '[' || argOrder == ']'; }
76 bool IsArrayedTexture(const char argOrder) { return argOrder == '@'; }
77 bool IsTextureMS(const char argOrder)      { return argOrder == '$' || argOrder == '&'; }
78 bool IsMS(const char argOrder)             { return IsTextureMS(argOrder) || argOrder == ']'; }
79 bool IsBuffer(const char argOrder)         { return argOrder == '*' || argOrder == '~'; }
80 bool IsImage(const char argOrder)          { return argOrder == '!' || argOrder == '#' || argOrder == '~'; }
81
82 bool IsTextureType(const char argOrder)
83 {
84     return IsTextureNonMS(argOrder) || IsArrayedTexture(argOrder) ||
85            IsTextureMS(argOrder) || IsBuffer(argOrder) || IsImage(argOrder);
86 }
87
88 // Reject certain combinations that are illegal sample methods.  For example,
89 // 3D arrays.
90 bool IsIllegalSample(const glslang::TString& name, const char* argOrder, int dim0)
91 {
92     const bool isArrayed = IsArrayed(*argOrder);
93     const bool isMS      = IsTextureMS(*argOrder);
94     const bool isBuffer  = IsBuffer(*argOrder);
95
96     // there are no 3D arrayed textures, or 3D SampleCmp(LevelZero)
97     if (dim0 == 3 && (isArrayed || name == "SampleCmp" || name == "SampleCmpLevelZero"))
98         return true;
99
100     const int numArgs = int(std::count(argOrder, argOrder + strlen(argOrder), ',')) + 1;
101
102     // Reject invalid offset forms with cubemaps
103     if (dim0 == 4) {
104         if ((name == "Sample"             && numArgs >= 4) ||
105             (name == "SampleBias"         && numArgs >= 5) ||
106             (name == "SampleCmp"          && numArgs >= 5) ||
107             (name == "SampleCmpLevelZero" && numArgs >= 5) ||
108             (name == "SampleGrad"         && numArgs >= 6) ||
109             (name == "SampleLevel"        && numArgs >= 5))
110             return true;
111     }
112
113     const bool isGather =
114         (name == "Gather" ||
115          name == "GatherRed" ||
116          name == "GatherGreen" ||
117          name == "GatherBlue"  ||
118          name == "GatherAlpha");
119
120     const bool isGatherCmp =
121         (name == "GatherCmp"      ||
122          name == "GatherCmpRed"   ||
123          name == "GatherCmpGreen" ||
124          name == "GatherCmpBlue"  ||
125          name == "GatherCmpAlpha");
126
127     // Reject invalid Gathers
128     if (isGather || isGatherCmp) {
129         if (dim0 == 1 || dim0 == 3)   // there are no 1D or 3D gathers
130             return true;
131
132         // no offset on cube or cube array gathers
133         if (dim0 == 4) {
134             if ((isGather && numArgs > 3) || (isGatherCmp && numArgs > 4))
135                 return true;
136         }
137     }
138
139     // Reject invalid Loads
140     if (name == "Load" && dim0 == 4)
141         return true; // Load does not support any cubemaps, arrayed or not.
142
143     // Multisample formats are only 2D and 2Darray
144     if (isMS && dim0 != 2)
145         return true;
146
147     // Buffer are only 1D
148     if (isBuffer && dim0 != 1)
149         return true;
150
151     return false;
152 }
153
154 // Return the number of the coordinate arg, if any
155 int CoordinateArgPos(const glslang::TString& name, bool isTexture)
156 {
157     if (!isTexture || (name == "GetDimensions"))
158         return -1;  // has none
159     else if (name == "Load")
160         return 1;
161     else
162         return 2;  // other texture methods are 2
163 }
164
165 // Some texture methods use an addition coordinate dimension for the mip
166 bool HasMipInCoord(const glslang::TString& name, bool isMS, bool isBuffer, bool isImage)
167 {
168     return name == "Load" && !isMS && !isBuffer && !isImage;
169 }
170
171 // LOD calculations don't pass the array level in the coordinate.
172 bool NoArrayCoord(const glslang::TString& name)
173 {
174     return name == "CalculateLevelOfDetail" || name == "CalculateLevelOfDetailUnclamped";
175 }
176
177 // Handle IO params marked with > or <
178 const char* IoParam(glslang::TString& s, const char* nthArgOrder)
179 {
180     if (*nthArgOrder == '>') {           // output params
181         ++nthArgOrder;
182         s.append("out ");
183     } else if (*nthArgOrder == '<') {    // input params
184         ++nthArgOrder;
185         s.append("in ");
186     }
187
188     return nthArgOrder;
189 }
190
191 // Handle repeated args
192 void HandleRepeatArg(const char*& arg, const char*& prev, const char* current)
193 {
194     if (*arg == ',' || *arg == '\0')
195         arg = prev;
196     else
197         prev = current;
198 }
199
200 // Return true for the end of a single argument key, which can be the end of the string, or
201 // the comma separator.
202 inline bool IsEndOfArg(const char* arg)
203 {
204     return arg == nullptr || *arg == '\0' || *arg == ',';
205 }
206
207 // If this is a fixed vector size, such as V3, return the size.  Else return 0.
208 int FixedVecSize(const char* arg)
209 {
210     while (!IsEndOfArg(arg)) {
211         if (isdigit(*arg))
212             return *arg - '0';
213         ++arg;
214     }
215
216     return 0; // none found.
217 }
218
219 // Create and return a type name.  This is done in GLSL, not HLSL conventions, until such
220 // time as builtins are parsed using the HLSL parser.
221 //
222 //    order:   S = scalar, V = vector, M = matrix
223 //    argType: F = float, D = double, I = int, U = uint, B = bool, S = sampler
224 //    dim0 = vector dimension, or matrix 1st dimension
225 //    dim1 = matrix 2nd dimension
226 glslang::TString& AppendTypeName(glslang::TString& s, const char* argOrder, const char* argType, int dim0, int dim1)
227 {
228     const bool isTranspose = (argOrder[0] == '^');
229     const bool isTexture   = IsTextureType(argOrder[0]);
230     const bool isArrayed   = IsArrayed(argOrder[0]);
231     const bool isSampler   = IsSamplerType(argType[0]);
232     const bool isMS        = IsMS(argOrder[0]);
233     const bool isBuffer    = IsBuffer(argOrder[0]);
234     const bool isImage     = IsImage(argOrder[0]);
235     const bool isSubpass   = IsSubpassInput(argOrder[0]);
236
237     char type  = *argType;
238
239     if (isTranspose) {  // Take transpose of matrix dimensions
240         std::swap(dim0, dim1);
241     } else if (isTexture || isSubpass) {
242         if (type == 'F')       // map base type to texture of that type.
243             type = 'T';        // e.g, int -> itexture, uint -> utexture, etc.
244         else if (type == 'I')
245             type = 'i';
246         else if (type == 'U')
247             type = 'u';
248     }
249
250     if (isTranspose)
251         ++argOrder;
252
253     char order = *argOrder;
254
255     if (UseHlslTypes) {
256         switch (type) {
257         case '-': s += "void";                                break;
258         case 'F': s += "float";                               break;
259         case 'D': s += "double";                              break;
260         case 'I': s += "int";                                 break;
261         case 'U': s += "uint";                                break;
262         case 'L': s += "int64_t";                             break;
263         case 'M': s += "uint64_t";                            break;
264         case 'B': s += "bool";                                break;
265         case 'S': s += "sampler";                             break;
266         case 's': s += "SamplerComparisonState";              break;
267         case 'T': s += ((isBuffer && isImage) ? "RWBuffer" :
268                         isSubpass ? "SubpassInput" :
269                         isBuffer ? "Buffer" :
270                         isImage  ? "RWTexture" : "Texture");  break;
271         case 'i': s += ((isBuffer && isImage) ? "RWBuffer" :
272                         isSubpass ? "SubpassInput" :
273                         isBuffer ? "Buffer" :
274                         isImage ? "RWTexture" : "Texture");   break;
275         case 'u': s += ((isBuffer && isImage) ? "RWBuffer" :
276                         isSubpass ? "SubpassInput" :
277                         isBuffer ? "Buffer" :
278                         isImage ? "RWTexture" : "Texture");   break;
279         default:  s += "UNKNOWN_TYPE";                        break;
280         }
281
282         if (isSubpass && isMS)
283             s += "MS";
284
285     } else {
286         switch (type) {
287         case '-': s += "void"; break;
288         case 'F': s += BaseTypeName(order, "float",  "vec",  "mat");  break;
289         case 'D': s += BaseTypeName(order, "double", "dvec", "dmat"); break;
290         case 'I': s += BaseTypeName(order, "int",    "ivec", "imat"); break;
291         case 'U': s += BaseTypeName(order, "uint",   "uvec", "umat"); break;
292         case 'B': s += BaseTypeName(order, "bool",   "bvec", "bmat"); break;
293         case 'S': s += "sampler";                                     break;
294         case 's': s += "samplerShadow";                               break;
295         case 'T': // fall through
296         case 'i': // ...
297         case 'u': // ...
298             if (type != 'T') // create itexture, utexture, etc
299                 s += type;
300
301             s += ((isImage && isBuffer) ? "imageBuffer"   :
302                   isSubpass             ? "subpassInput" :
303                   isImage               ? "image"         :
304                   isBuffer              ? "samplerBuffer" :
305                   "texture");
306             break;
307
308         default:  s += "UNKNOWN_TYPE"; break;
309         }
310     }
311
312     // handle fixed vector sizes, such as float3, and only ever 3.
313     const int fixedVecSize = FixedVecSize(argOrder);
314     if (fixedVecSize != 0)
315         dim0 = dim1 = fixedVecSize;
316
317     const char dim0Char = ('0' + char(dim0));
318     const char dim1Char = ('0' + char(dim1));
319
320     // Add sampler dimensions
321     if (isSampler || isTexture) {
322         if ((order == 'V' || isTexture) && !isBuffer) {
323             switch (dim0) {
324             case 1: s += "1D";                   break;
325             case 2: s += (isMS ? "2DMS" : "2D"); break;
326             case 3: s += "3D";                   break;
327             case 4: s += "Cube";                 break;
328             default: s += "UNKNOWN_SAMPLER";     break;
329             }
330         }
331     } else {
332         // Non-sampler type:
333         // verify dimensions
334         if (((order == 'V' || order == 'M') && (dim0 < 1 || dim0 > 4)) ||
335             (order == 'M' && (dim1 < 1 || dim1 > 4))) {
336             s += "UNKNOWN_DIMENSION";
337             return s;
338         }
339
340         switch (order) {
341         case '-': break;  // no dimensions for voids
342         case 'S': break;  // no dimensions on scalars
343         case 'V':
344             s += dim0Char;
345             break;
346         case 'M':
347             s += dim0Char;
348             s += 'x';
349             s += dim1Char;
350             break;
351         default:
352             break;
353         }
354     }
355
356     // handle arrayed textures
357     if (isArrayed)
358         s += "Array";
359
360     // For HLSL, append return type for texture types
361     if (UseHlslTypes) {
362         switch (type) {
363         case 'i': s += "<int";   s += dim0Char; s += ">"; break;
364         case 'u': s += "<uint";  s += dim0Char; s += ">"; break;
365         case 'T': s += "<float"; s += dim0Char; s += ">"; break;
366         default: break;
367         }
368     }
369
370     return s;
371 }
372
373 // The GLSL parser can be used to parse a subset of HLSL prototypes.  However, many valid HLSL prototypes
374 // are not valid GLSL prototypes.  This rejects the invalid ones.  Thus, there is a single switch below
375 // to enable creation of the entire HLSL space.
376 inline bool IsValid(const char* cname, char retOrder, char retType, char argOrder, char argType, int dim0, int dim1)
377 {
378     const bool isVec = (argOrder == 'V');
379     const bool isMat = (argOrder == 'M');
380
381     const std::string name(cname);
382
383     // these do not have vec1 versions
384     if (dim0 == 1 && (name == "normalize" || name == "reflect" || name == "refract"))
385         return false;
386
387     if (!IsTextureType(argOrder) && (isVec && dim0 == 1)) // avoid vec1
388         return false;
389
390     if (UseHlslTypes) {
391         // NO further restrictions for HLSL
392     } else {
393         // GLSL parser restrictions
394         if ((isMat && (argType == 'I' || argType == 'U' || argType == 'B')) ||
395             (retOrder == 'M' && (retType == 'I' || retType == 'U' || retType == 'B')))
396             return false;
397
398         if (isMat && dim0 == 1 && dim1 == 1)  // avoid mat1x1
399             return false;
400
401         if (isMat && dim1 == 1)  // TODO: avoid mat Nx1 until we find the right GLSL profile
402             return false;
403
404         if (name == "GetRenderTargetSamplePosition" ||
405             name == "tex1D" ||
406             name == "tex1Dgrad")
407             return false;
408     }
409
410     return true;
411 }
412
413 // return position of end of argument specifier
414 inline const char* FindEndOfArg(const char* arg)
415 {
416     while (!IsEndOfArg(arg))
417         ++arg;
418
419     return *arg == '\0' ? nullptr : arg;
420 }
421
422 // Return pointer to beginning of Nth argument specifier in the string.
423 inline const char* NthArg(const char* arg, int n)
424 {
425     for (int x=0; x<n && arg; ++x)
426         if ((arg = FindEndOfArg(arg)) != nullptr)
427             ++arg;  // skip arg separator
428
429     return arg;
430 }
431
432 inline void FindVectorMatrixBounds(const char* argOrder, int fixedVecSize, int& dim0Min, int& dim0Max, int& /*dim1Min*/, int& dim1Max)
433 {
434     for (int arg = 0; ; ++arg) {
435         const char* nthArgOrder(NthArg(argOrder, arg));
436         if (nthArgOrder == nullptr)
437             break;
438         else if (*nthArgOrder == 'V' || IsSubpassInput(*nthArgOrder))
439             dim0Max = 4;
440         else if (*nthArgOrder == 'M')
441             dim0Max = dim1Max = 4;
442     }
443
444     if (fixedVecSize > 0) // handle fixed sized vectors
445         dim0Min = dim0Max = fixedVecSize;
446 }
447
448 } // end anonymous namespace
449
450 namespace glslang {
451
452 TBuiltInParseablesHlsl::TBuiltInParseablesHlsl()
453 {
454 }
455
456 //
457 // Handle creation of mat*mat specially, since it doesn't fall conveniently out of
458 // the generic prototype creation code below.
459 //
460 void TBuiltInParseablesHlsl::createMatTimesMat()
461 {
462     TString& s = commonBuiltins;
463
464     const int first = (UseHlslTypes ? 1 : 2);
465
466     for (int xRows = first; xRows <=4; xRows++) {
467         for (int xCols = first; xCols <=4; xCols++) {
468             const int yRows = xCols;
469             for (int yCols = first; yCols <=4; yCols++) {
470                 const int retRows = xRows;
471                 const int retCols = yCols;
472
473                 // Create a mat * mat of the appropriate dimensions
474                 AppendTypeName(s, "M", "F", retRows, retCols);  // add return type
475                 s.append(" ");                                  // space between type and name
476                 s.append("mul");                                // intrinsic name
477                 s.append("(");                                  // open paren
478
479                 AppendTypeName(s, "M", "F", xRows, xCols);      // add X input
480                 s.append(", ");
481                 AppendTypeName(s, "M", "F", yRows, yCols);      // add Y input
482
483                 s.append(");\n");                               // close paren
484             }
485
486             // Create M*V
487             AppendTypeName(s, "V", "F", xRows, 1);          // add return type
488             s.append(" ");                                  // space between type and name
489             s.append("mul");                                // intrinsic name
490             s.append("(");                                  // open paren
491
492             AppendTypeName(s, "M", "F", xRows, xCols);      // add X input
493             s.append(", ");
494             AppendTypeName(s, "V", "F", xCols, 1);          // add Y input
495
496             s.append(");\n");                               // close paren
497
498             // Create V*M
499             AppendTypeName(s, "V", "F", xCols, 1);          // add return type
500             s.append(" ");                                  // space between type and name
501             s.append("mul");                                // intrinsic name
502             s.append("(");                                  // open paren
503
504             AppendTypeName(s, "V", "F", xRows, 1);          // add Y input
505             s.append(", ");
506             AppendTypeName(s, "M", "F", xRows, xCols);      // add X input
507
508             s.append(");\n");                               // close paren
509         }
510     }
511 }
512
513 //
514 // Add all context-independent built-in functions and variables that are present
515 // for the given version and profile.  Share common ones across stages, otherwise
516 // make stage-specific entries.
517 //
518 // Most built-ins variables can be added as simple text strings.  Some need to
519 // be added programmatically, which is done later in IdentifyBuiltIns() below.
520 //
521 void TBuiltInParseablesHlsl::initialize(int /*version*/, EProfile /*profile*/, const SpvVersion& /*spvVersion*/)
522 {
523     static const EShLanguageMask EShLangAll    = EShLanguageMask(EShLangCount - 1);
524
525     // These are the actual stage masks defined in the documentation, in case they are
526     // needed for future validation.  For now, they are commented out, and set below
527     // to EShLangAll, to allow any intrinsic to be used in any shader, which is legal
528     // if it is not called.
529     //
530     // static const EShLanguageMask EShLangPSCS   = EShLanguageMask(EShLangFragmentMask | EShLangComputeMask);
531     // static const EShLanguageMask EShLangVSPSGS = EShLanguageMask(EShLangVertexMask | EShLangFragmentMask | EShLangGeometryMask);
532     // static const EShLanguageMask EShLangCS     = EShLangComputeMask;
533     // static const EShLanguageMask EShLangPS     = EShLangFragmentMask;
534     // static const EShLanguageMask EShLangHS     = EShLangTessControlMask;
535
536     // This set uses EShLangAll for everything.
537     static const EShLanguageMask EShLangPSCS   = EShLangAll;
538     static const EShLanguageMask EShLangVSPSGS = EShLangAll;
539     static const EShLanguageMask EShLangCS     = EShLangAll;
540     static const EShLanguageMask EShLangPS     = EShLangAll;
541     static const EShLanguageMask EShLangHS     = EShLangAll;
542     static const EShLanguageMask EShLangGS     = EShLangAll;
543
544     // This structure encodes the prototype information for each HLSL intrinsic.
545     // Because explicit enumeration would be cumbersome, it's procedurally generated.
546     // orderKey can be:
547     //   S = scalar, V = vector, M = matrix, - = void
548     // typekey can be:
549     //   D = double, F = float, U = uint, I = int, B = bool, S = sampler, s = shadowSampler, M = uint64_t, L = int64_t
550     // An empty order or type key repeats the first one.  E.g: SVM,, means 3 args each of SVM.
551     // '>' as first letter of order creates an output parameter
552     // '<' as first letter of order creates an input parameter
553     // '^' as first letter of order takes transpose dimensions
554     // '%' as first letter of order creates texture of given F/I/U type (texture, itexture, etc)
555     // '@' as first letter of order creates arrayed texture of given type
556     // '$' / '&' as first letter of order creates 2DMS / 2DMSArray textures
557     // '*' as first letter of order creates buffer object
558     // '!' as first letter of order creates image object
559     // '#' as first letter of order creates arrayed image object
560     // '~' as first letter of order creates an image buffer object
561     // '[' / ']' as first letter of order creates a SubpassInput/SubpassInputMS object
562
563     static const struct {
564         const char*   name;      // intrinsic name
565         const char*   retOrder;  // return type key: empty matches order of 1st argument
566         const char*   retType;   // return type key: empty matches type of 1st argument
567         const char*   argOrder;  // argument order key
568         const char*   argType;   // argument type key
569         unsigned int  stage;     // stage mask
570         bool          method;    // true if it's a method.
571     } hlslIntrinsics[] = {
572         // name                               retOrd   retType    argOrder          argType          stage mask     method
573         // ----------------------------------------------------------------------------------------------------------------
574         { "abort",                            nullptr, nullptr,   "-",              "-",             EShLangAll,    false },
575         { "abs",                              nullptr, nullptr,   "SVM",            "DFUI",          EShLangAll,    false },
576         { "acos",                             nullptr, nullptr,   "SVM",            "F",             EShLangAll,    false },
577         { "all",                              "S",    "B",        "SVM",            "BFIU",          EShLangAll,    false },
578         { "AllMemoryBarrier",                 nullptr, nullptr,   "-",              "-",             EShLangCS,     false },
579         { "AllMemoryBarrierWithGroupSync",    nullptr, nullptr,   "-",              "-",             EShLangCS,     false },
580         { "any",                              "S",     "B",       "SVM",            "BFIU",          EShLangAll,    false },
581         { "asdouble",                         "S",     "D",       "S,",             "UI,",           EShLangAll,    false },
582         { "asdouble",                         "V2",    "D",       "V2,",            "UI,",           EShLangAll,    false },
583         { "asfloat",                          nullptr, "F",       "SVM",            "BFIU",          EShLangAll,    false },
584         { "asin",                             nullptr, nullptr,   "SVM",            "F",             EShLangAll,    false },
585         { "asint",                            nullptr, "I",       "SVM",            "FIU",           EShLangAll,    false },
586         { "asuint",                           nullptr, "U",       "SVM",            "FIU",           EShLangAll,    false },
587         { "atan",                             nullptr, nullptr,   "SVM",            "F",             EShLangAll,    false },
588         { "atan2",                            nullptr, nullptr,   "SVM,",           "F,",            EShLangAll,    false },
589         { "ceil",                             nullptr, nullptr,   "SVM",            "F",             EShLangAll,    false },
590         { "CheckAccessFullyMapped",           "S",     "B" ,      "S",              "U",             EShLangPSCS,   false },
591         { "clamp",                            nullptr, nullptr,   "SVM,,",          "FUI,,",         EShLangAll,    false },
592         { "clip",                             "-",     "-",       "SVM",            "FUI",           EShLangPS,     false },
593         { "cos",                              nullptr, nullptr,   "SVM",            "F",             EShLangAll,    false },
594         { "cosh",                             nullptr, nullptr,   "SVM",            "F",             EShLangAll,    false },
595         { "countbits",                        nullptr, nullptr,   "SV",             "UI",            EShLangAll,    false },
596         { "cross",                            nullptr, nullptr,   "V3,",            "F,",            EShLangAll,    false },
597         { "D3DCOLORtoUBYTE4",                 "V4",    "I",       "V4",             "F",             EShLangAll,    false },
598         { "ddx",                              nullptr, nullptr,   "SVM",            "F",             EShLangPS,     false },
599         { "ddx_coarse",                       nullptr, nullptr,   "SVM",            "F",             EShLangPS,     false },
600         { "ddx_fine",                         nullptr, nullptr,   "SVM",            "F",             EShLangPS,     false },
601         { "ddy",                              nullptr, nullptr,   "SVM",            "F",             EShLangPS,     false },
602         { "ddy_coarse",                       nullptr, nullptr,   "SVM",            "F",             EShLangPS,     false },
603         { "ddy_fine",                         nullptr, nullptr,   "SVM",            "F",             EShLangPS,     false },
604         { "degrees",                          nullptr, nullptr,   "SVM",            "F",             EShLangAll,    false },
605         { "determinant",                      "S",     "F",       "M",              "F",             EShLangAll,    false },
606         { "DeviceMemoryBarrier",              nullptr, nullptr,   "-",              "-",             EShLangPSCS,   false },
607         { "DeviceMemoryBarrierWithGroupSync", nullptr, nullptr,   "-",              "-",             EShLangCS,     false },
608         { "distance",                         "S",     "F",       "SV,",            "F,",            EShLangAll,    false },
609         { "dot",                              "S",     nullptr,   "SV,",            "FI,",           EShLangAll,    false },
610         { "dst",                              nullptr, nullptr,   "V4,",            "F,",            EShLangAll,    false },
611         // { "errorf",                           "-",     "-",       "",             "",             EShLangAll,    false }, TODO: varargs
612         { "EvaluateAttributeAtCentroid",      nullptr, nullptr,   "SVM",            "F",             EShLangPS,     false },
613         { "EvaluateAttributeAtSample",        nullptr, nullptr,   "SVM,S",          "F,U",           EShLangPS,     false },
614         { "EvaluateAttributeSnapped",         nullptr, nullptr,   "SVM,V2",         "F,I",           EShLangPS,     false },
615         { "exp",                              nullptr, nullptr,   "SVM",            "F",             EShLangAll,    false },
616         { "exp2",                             nullptr, nullptr,   "SVM",            "F",             EShLangAll,    false },
617         { "f16tof32",                         nullptr, "F",       "SV",             "U",             EShLangAll,    false },
618         { "f32tof16",                         nullptr, "U",       "SV",             "F",             EShLangAll,    false },
619         { "faceforward",                      nullptr, nullptr,   "V,,",            "F,,",           EShLangAll,    false },
620         { "firstbithigh",                     nullptr, nullptr,   "SV",             "UI",            EShLangAll,    false },
621         { "firstbitlow",                      nullptr, nullptr,   "SV",             "UI",            EShLangAll,    false },
622         { "floor",                            nullptr, nullptr,   "SVM",            "F",             EShLangAll,    false },
623         { "fma",                              nullptr, nullptr,   "SVM,,",          "D,,",           EShLangAll,    false },
624         { "fmod",                             nullptr, nullptr,   "SVM,",           "F,",            EShLangAll,    false },
625         { "frac",                             nullptr, nullptr,   "SVM",            "F",             EShLangAll,    false },
626         { "frexp",                            nullptr, nullptr,   "SVM,",           "F,",            EShLangAll,    false },
627         { "fwidth",                           nullptr, nullptr,   "SVM",            "F",             EShLangPS,     false },
628         { "GetRenderTargetSampleCount",       "S",     "U",       "-",              "-",             EShLangAll,    false },
629         { "GetRenderTargetSamplePosition",    "V2",    "F",       "V1",             "I",             EShLangAll,    false },
630         { "GroupMemoryBarrier",               nullptr, nullptr,   "-",              "-",             EShLangCS,     false },
631         { "GroupMemoryBarrierWithGroupSync",  nullptr, nullptr,   "-",              "-",             EShLangCS,     false },
632         { "InterlockedAdd",                   "-",     "-",       "SVM,,>",         "UI,,",          EShLangPSCS,   false },
633         { "InterlockedAdd",                   "-",     "-",       "SVM,",           "UI,",           EShLangPSCS,   false },
634         { "InterlockedAnd",                   "-",     "-",       "SVM,,>",         "UI,,",          EShLangPSCS,   false },
635         { "InterlockedAnd",                   "-",     "-",       "SVM,",           "UI,",           EShLangPSCS,   false },
636         { "InterlockedCompareExchange",       "-",     "-",       "SVM,,,>",        "UI,,,",         EShLangPSCS,   false },
637         { "InterlockedCompareStore",          "-",     "-",       "SVM,,",          "UI,,",          EShLangPSCS,   false },
638         { "InterlockedExchange",              "-",     "-",       "SVM,,>",         "UI,,",          EShLangPSCS,   false },
639         { "InterlockedMax",                   "-",     "-",       "SVM,,>",         "UI,,",          EShLangPSCS,   false },
640         { "InterlockedMax",                   "-",     "-",       "SVM,",           "UI,",           EShLangPSCS,   false },
641         { "InterlockedMin",                   "-",     "-",       "SVM,,>",         "UI,,",          EShLangPSCS,   false },
642         { "InterlockedMin",                   "-",     "-",       "SVM,",           "UI,",           EShLangPSCS,   false },
643         { "InterlockedOr",                    "-",     "-",       "SVM,,>",         "UI,,",          EShLangPSCS,   false },
644         { "InterlockedOr",                    "-",     "-",       "SVM,",           "UI,",           EShLangPSCS,   false },
645         { "InterlockedXor",                   "-",     "-",       "SVM,,>",         "UI,,",          EShLangPSCS,   false },
646         { "InterlockedXor",                   "-",     "-",       "SVM,",           "UI,",           EShLangPSCS,   false },
647         { "isfinite",                         nullptr, "B" ,      "SVM",            "F",             EShLangAll,    false },
648         { "isinf",                            nullptr, "B" ,      "SVM",            "F",             EShLangAll,    false },
649         { "isnan",                            nullptr, "B" ,      "SVM",            "F",             EShLangAll,    false },
650         { "ldexp",                            nullptr, nullptr,   "SVM,",           "F,",            EShLangAll,    false },
651         { "length",                           "S",     "F",       "SV",             "F",             EShLangAll,    false },
652         { "lerp",                             nullptr, nullptr,   "VM,,",           "F,,",           EShLangAll,    false },
653         { "lerp",                             nullptr, nullptr,   "SVM,,S",         "F,,",           EShLangAll,    false },
654         { "lit",                              "V4",    "F",       "S,,",            "F,,",           EShLangAll,    false },
655         { "log",                              nullptr, nullptr,   "SVM",            "F",             EShLangAll,    false },
656         { "log10",                            nullptr, nullptr,   "SVM",            "F",             EShLangAll,    false },
657         { "log2",                             nullptr, nullptr,   "SVM",            "F",             EShLangAll,    false },
658         { "mad",                              nullptr, nullptr,   "SVM,,",          "DFUI,,",        EShLangAll,    false },
659         { "max",                              nullptr, nullptr,   "SVM,",           "FIU,",          EShLangAll,    false },
660         { "min",                              nullptr, nullptr,   "SVM,",           "FIU,",          EShLangAll,    false },
661         { "modf",                             nullptr, nullptr,   "SVM,>",          "FIU,",          EShLangAll,    false },
662         { "msad4",                            "V4",    "U",       "S,V2,V4",        "U,,",           EShLangAll,    false },
663         { "mul",                              "S",     nullptr,   "S,S",            "FI,",           EShLangAll,    false },
664         { "mul",                              "V",     nullptr,   "S,V",            "FI,",           EShLangAll,    false },
665         { "mul",                              "M",     nullptr,   "S,M",            "FI,",           EShLangAll,    false },
666         { "mul",                              "V",     nullptr,   "V,S",            "FI,",           EShLangAll,    false },
667         { "mul",                              "S",     nullptr,   "V,V",            "FI,",           EShLangAll,    false },
668         { "mul",                              "M",     nullptr,   "M,S",            "FI,",           EShLangAll,    false },
669         // mat*mat form of mul is handled in createMatTimesMat()
670         { "noise",                            "S",     "F",       "V",              "F",             EShLangPS,     false },
671         { "normalize",                        nullptr, nullptr,   "V",              "F",             EShLangAll,    false },
672         { "pow",                              nullptr, nullptr,   "SVM,",           "F,",            EShLangAll,    false },
673         // { "printf",                           "-",     "-",       "",            "",              EShLangAll,    false }, TODO: varargs
674         { "Process2DQuadTessFactorsAvg",      "-",     "-",       "V4,V2,>V4,>V2,", "F,,,,",         EShLangHS,     false },
675         { "Process2DQuadTessFactorsMax",      "-",     "-",       "V4,V2,>V4,>V2,", "F,,,,",         EShLangHS,     false },
676         { "Process2DQuadTessFactorsMin",      "-",     "-",       "V4,V2,>V4,>V2,", "F,,,,",         EShLangHS,     false },
677         { "ProcessIsolineTessFactors",        "-",     "-",       "S,,>,>",         "F,,,",          EShLangHS,     false },
678         { "ProcessQuadTessFactorsAvg",        "-",     "-",       "V4,S,>V4,>V2,",  "F,,,,",         EShLangHS,     false },
679         { "ProcessQuadTessFactorsMax",        "-",     "-",       "V4,S,>V4,>V2,",  "F,,,,",         EShLangHS,     false },
680         { "ProcessQuadTessFactorsMin",        "-",     "-",       "V4,S,>V4,>V2,",  "F,,,,",         EShLangHS,     false },
681         { "ProcessTriTessFactorsAvg",         "-",     "-",       "V3,S,>V3,>S,",   "F,,,,",         EShLangHS,     false },
682         { "ProcessTriTessFactorsMax",         "-",     "-",       "V3,S,>V3,>S,",   "F,,,,",         EShLangHS,     false },
683         { "ProcessTriTessFactorsMin",         "-",     "-",       "V3,S,>V3,>S,",   "F,,,,",         EShLangHS,     false },
684         { "radians",                          nullptr, nullptr,   "SVM",            "F",             EShLangAll,    false },
685         { "rcp",                              nullptr, nullptr,   "SVM",            "FD",            EShLangAll,    false },
686         { "reflect",                          nullptr, nullptr,   "V,",             "F,",            EShLangAll,    false },
687         { "refract",                          nullptr, nullptr,   "V,V,S",          "F,,",           EShLangAll,    false },
688         { "reversebits",                      nullptr, nullptr,   "SV",             "UI",            EShLangAll,    false },
689         { "round",                            nullptr, nullptr,   "SVM",            "F",             EShLangAll,    false },
690         { "rsqrt",                            nullptr, nullptr,   "SVM",            "F",             EShLangAll,    false },
691         { "saturate",                         nullptr, nullptr ,  "SVM",            "F",             EShLangAll,    false },
692         { "sign",                             nullptr, nullptr,   "SVM",            "FI",            EShLangAll,    false },
693         { "sin",                              nullptr, nullptr,   "SVM",            "F",             EShLangAll,    false },
694         { "sincos",                           "-",     "-",       "SVM,>,>",        "F,,",           EShLangAll,    false },
695         { "sinh",                             nullptr, nullptr,   "SVM",            "F",             EShLangAll,    false },
696         { "smoothstep",                       nullptr, nullptr,   "SVM,,",          "F,,",           EShLangAll,    false },
697         { "sqrt",                             nullptr, nullptr,   "SVM",            "F",             EShLangAll,    false },
698         { "step",                             nullptr, nullptr,   "SVM,",           "F,",            EShLangAll,    false },
699         { "tan",                              nullptr, nullptr,   "SVM",            "F",             EShLangAll,    false },
700         { "tanh",                             nullptr, nullptr,   "SVM",            "F",             EShLangAll,    false },
701         { "tex1D",                            "V4",    "F",       "S,S",            "S,F",           EShLangPS,     false },
702         { "tex1D",                            "V4",    "F",       "S,S,V1,",        "S,F,,",         EShLangPS,     false },
703         { "tex1Dbias",                        "V4",    "F",       "S,V4",           "S,F",           EShLangPS,     false },
704         { "tex1Dgrad",                        "V4",    "F",       "S,,,",           "S,F,,",         EShLangPS,     false },
705         { "tex1Dlod",                         "V4",    "F",       "S,V4",           "S,F",           EShLangPS,     false },
706         { "tex1Dproj",                        "V4",    "F",       "S,V4",           "S,F",           EShLangPS,     false },
707         { "tex2D",                            "V4",    "F",       "V2,",            "S,F",           EShLangPS,     false },
708         { "tex2D",                            "V4",    "F",       "V2,,,",          "S,F,,",         EShLangPS,     false },
709         { "tex2Dbias",                        "V4",    "F",       "V2,V4",          "S,F",           EShLangPS,     false },
710         { "tex2Dgrad",                        "V4",    "F",       "V2,,,",          "S,F,,",         EShLangPS,     false },
711         { "tex2Dlod",                         "V4",    "F",       "V2,V4",          "S,F",           EShLangAll,    false },
712         { "tex2Dproj",                        "V4",    "F",       "V2,V4",          "S,F",           EShLangPS,     false },
713         { "tex3D",                            "V4",    "F",       "V3,",            "S,F",           EShLangPS,     false },
714         { "tex3D",                            "V4",    "F",       "V3,,,",          "S,F,,",         EShLangPS,     false },
715         { "tex3Dbias",                        "V4",    "F",       "V3,V4",          "S,F",           EShLangPS,     false },
716         { "tex3Dgrad",                        "V4",    "F",       "V3,,,",          "S,F,,",         EShLangPS,     false },
717         { "tex3Dlod",                         "V4",    "F",       "V3,V4",          "S,F",           EShLangPS,     false },
718         { "tex3Dproj",                        "V4",    "F",       "V3,V4",          "S,F",           EShLangPS,     false },
719         { "texCUBE",                          "V4",    "F",       "V4,V3",          "S,F",           EShLangPS,     false },
720         { "texCUBE",                          "V4",    "F",       "V4,V3,,",        "S,F,,",         EShLangPS,     false },
721         { "texCUBEbias",                      "V4",    "F",       "V4,",            "S,F",           EShLangPS,     false },
722         { "texCUBEgrad",                      "V4",    "F",       "V4,V3,,",        "S,F,,",         EShLangPS,     false },
723         { "texCUBElod",                       "V4",    "F",       "V4,",            "S,F",           EShLangPS,     false },
724         { "texCUBEproj",                      "V4",    "F",       "V4,",            "S,F",           EShLangPS,     false },
725         { "transpose",                        "^M",    nullptr,   "M",              "FUIB",          EShLangAll,    false },
726         { "trunc",                            nullptr, nullptr,   "SVM",            "F",             EShLangAll,    false },
727
728         // Texture object methods.  Return type can be overridden by shader declaration.
729         // !O = no offset, O = offset
730         { "Sample",             /*!O*/        "V4",    nullptr,   "%@,S,V",         "FIU,S,F",        EShLangPS,    true },
731         { "Sample",             /* O*/        "V4",    nullptr,   "%@,S,V,",        "FIU,S,F,I",      EShLangPS,    true },
732
733         { "SampleBias",         /*!O*/        "V4",    nullptr,   "%@,S,V,S",       "FIU,S,F,",       EShLangPS,    true },
734         { "SampleBias",         /* O*/        "V4",    nullptr,   "%@,S,V,S,V",     "FIU,S,F,,I",     EShLangPS,    true },
735
736         // TODO: FXC accepts int/uint samplers here.  unclear what that means.
737         { "SampleCmp",          /*!O*/        "S",     "F",       "%@,S,V,S",       "FIU,s,F,",       EShLangPS,    true },
738         { "SampleCmp",          /* O*/        "S",     "F",       "%@,S,V,S,V",     "FIU,s,F,,I",     EShLangPS,    true },
739
740         // TODO: FXC accepts int/uint samplers here.  unclear what that means.
741         { "SampleCmpLevelZero", /*!O*/        "S",     "F",       "%@,S,V,S",       "FIU,s,F,F",      EShLangPS,    true },
742         { "SampleCmpLevelZero", /* O*/        "S",     "F",       "%@,S,V,S,V",     "FIU,s,F,F,I",    EShLangPS,    true },
743
744         { "SampleGrad",         /*!O*/        "V4",    nullptr,   "%@,S,V,,",       "FIU,S,F,,",      EShLangAll,   true },
745         { "SampleGrad",         /* O*/        "V4",    nullptr,   "%@,S,V,,,",      "FIU,S,F,,,I",    EShLangAll,   true },
746
747         { "SampleLevel",        /*!O*/        "V4",    nullptr,   "%@,S,V,S",       "FIU,S,F,",       EShLangAll,   true },
748         { "SampleLevel",        /* O*/        "V4",    nullptr,   "%@,S,V,S,V",     "FIU,S,F,,I",     EShLangAll,   true },
749
750         { "Load",               /*!O*/        "V4",    nullptr,   "%@,V",           "FIU,I",          EShLangAll,   true },
751         { "Load",               /* O*/        "V4",    nullptr,   "%@,V,V",         "FIU,I,I",        EShLangAll,   true },
752         { "Load", /* +sampleidex*/            "V4",    nullptr,   "$&,V,S",         "FIU,I,I",        EShLangAll,   true },
753         { "Load", /* +samplindex, offset*/    "V4",    nullptr,   "$&,V,S,V",       "FIU,I,I,I",      EShLangAll,   true },
754
755         // RWTexture loads
756         { "Load",                             "V4",    nullptr,   "!#,V",           "FIU,I",          EShLangAll,   true },
757         // (RW)Buffer loads
758         { "Load",                             "V4",    nullptr,   "~*1,V",          "FIU,I",          EShLangAll,   true },
759
760         { "Gather",             /*!O*/        "V4",    nullptr,   "%@,S,V",         "FIU,S,F",        EShLangAll,   true },
761         { "Gather",             /* O*/        "V4",    nullptr,   "%@,S,V,V",       "FIU,S,F,I",      EShLangAll,   true },
762
763         { "CalculateLevelOfDetail",           "S",     "F",       "%@,S,V",         "FUI,S,F",        EShLangPS,    true },
764         { "CalculateLevelOfDetailUnclamped",  "S",     "F",       "%@,S,V",         "FUI,S,F",        EShLangPS,    true },
765
766         { "GetSamplePosition",                "V2",    "F",       "$&2,S",          "FUI,I",          EShLangVSPSGS,true },
767
768         //
769         // UINT Width
770         // UINT MipLevel, UINT Width, UINT NumberOfLevels
771         { "GetDimensions",   /* 1D */         "-",     "-",       "%!~1,>S",        "FUI,U",          EShLangAll,   true },
772         { "GetDimensions",   /* 1D */         "-",     "-",       "%!~1,>S",        "FUI,F",          EShLangAll,   true },
773         { "GetDimensions",   /* 1D */         "-",     "-",       "%1,S,>S,",       "FUI,U,,",        EShLangAll,   true },
774         { "GetDimensions",   /* 1D */         "-",     "-",       "%1,S,>S,",       "FUI,U,F,",       EShLangAll,   true },
775
776         // UINT Width, UINT Elements
777         // UINT MipLevel, UINT Width, UINT Elements, UINT NumberOfLevels
778         { "GetDimensions",   /* 1DArray */    "-",     "-",       "@#1,>S,",        "FUI,U,",         EShLangAll,   true },
779         { "GetDimensions",   /* 1DArray */    "-",     "-",       "@#1,>S,",        "FUI,F,",         EShLangAll,   true },
780         { "GetDimensions",   /* 1DArray */    "-",     "-",       "@1,S,>S,,",      "FUI,U,,,",       EShLangAll,   true },
781         { "GetDimensions",   /* 1DArray */    "-",     "-",       "@1,S,>S,,",      "FUI,U,F,,",      EShLangAll,   true },
782
783         // UINT Width, UINT Height
784         // UINT MipLevel, UINT Width, UINT Height, UINT NumberOfLevels
785         { "GetDimensions",   /* 2D */         "-",     "-",       "%!2,>S,",        "FUI,U,",         EShLangAll,   true },
786         { "GetDimensions",   /* 2D */         "-",     "-",       "%!2,>S,",        "FUI,F,",         EShLangAll,   true },
787         { "GetDimensions",   /* 2D */         "-",     "-",       "%2,S,>S,,",      "FUI,U,,,",       EShLangAll,   true },
788         { "GetDimensions",   /* 2D */         "-",     "-",       "%2,S,>S,,",      "FUI,U,F,,",      EShLangAll,   true },
789
790         // UINT Width, UINT Height, UINT Elements
791         // UINT MipLevel, UINT Width, UINT Height, UINT Elements, UINT NumberOfLevels
792         { "GetDimensions",   /* 2DArray */    "-",     "-",       "@#2,>S,,",       "FUI,U,,",        EShLangAll,   true },
793         { "GetDimensions",   /* 2DArray */    "-",     "-",       "@#2,>S,,",       "FUI,F,F,F",      EShLangAll,   true },
794         { "GetDimensions",   /* 2DArray */    "-",     "-",       "@2,S,>S,,,",     "FUI,U,,,,",      EShLangAll,   true },
795         { "GetDimensions",   /* 2DArray */    "-",     "-",       "@2,S,>S,,,",     "FUI,U,F,,,",     EShLangAll,   true },
796
797         // UINT Width, UINT Height, UINT Depth
798         // UINT MipLevel, UINT Width, UINT Height, UINT Depth, UINT NumberOfLevels
799         { "GetDimensions",   /* 3D */         "-",     "-",       "%!3,>S,,",       "FUI,U,,",        EShLangAll,   true },
800         { "GetDimensions",   /* 3D */         "-",     "-",       "%!3,>S,,",       "FUI,F,,",        EShLangAll,   true },
801         { "GetDimensions",   /* 3D */         "-",     "-",       "%3,S,>S,,,",     "FUI,U,,,,",      EShLangAll,   true },
802         { "GetDimensions",   /* 3D */         "-",     "-",       "%3,S,>S,,,",     "FUI,U,F,,,",     EShLangAll,   true },
803
804         // UINT Width, UINT Height
805         // UINT MipLevel, UINT Width, UINT Height, UINT NumberOfLevels
806         { "GetDimensions",   /* Cube */       "-",     "-",       "%4,>S,",         "FUI,U,",         EShLangAll,   true },
807         { "GetDimensions",   /* Cube */       "-",     "-",       "%4,>S,",         "FUI,F,",         EShLangAll,   true },
808         { "GetDimensions",   /* Cube */       "-",     "-",       "%4,S,>S,,",      "FUI,U,,,",       EShLangAll,   true },
809         { "GetDimensions",   /* Cube */       "-",     "-",       "%4,S,>S,,",      "FUI,U,F,,",      EShLangAll,   true },
810
811         // UINT Width, UINT Height, UINT Elements
812         // UINT MipLevel, UINT Width, UINT Height, UINT Elements, UINT NumberOfLevels
813         { "GetDimensions",   /* CubeArray */  "-",     "-",       "@4,>S,,",        "FUI,U,,",        EShLangAll,   true },
814         { "GetDimensions",   /* CubeArray */  "-",     "-",       "@4,>S,,",        "FUI,F,,",        EShLangAll,   true },
815         { "GetDimensions",   /* CubeArray */  "-",     "-",       "@4,S,>S,,,",     "FUI,U,,,,",      EShLangAll,   true },
816         { "GetDimensions",   /* CubeArray */  "-",     "-",       "@4,S,>S,,,",     "FUI,U,F,,,",     EShLangAll,   true },
817
818         // UINT Width, UINT Height, UINT Samples
819         // UINT Width, UINT Height, UINT Elements, UINT Samples
820         { "GetDimensions",   /* 2DMS */       "-",     "-",       "$2,>S,,",        "FUI,U,,",        EShLangAll,   true },
821         { "GetDimensions",   /* 2DMS */       "-",     "-",       "$2,>S,,",        "FUI,U,,",        EShLangAll,   true },
822         { "GetDimensions",   /* 2DMSArray */  "-",     "-",       "&2,>S,,,",       "FUI,U,,,",       EShLangAll,   true },
823         { "GetDimensions",   /* 2DMSArray */  "-",     "-",       "&2,>S,,,",       "FUI,U,,,",       EShLangAll,   true },
824
825         // SM5 texture methods
826         { "GatherRed",       /*!O*/           "V4",    nullptr,   "%@,S,V",         "FIU,S,F",        EShLangAll,   true },
827         { "GatherRed",       /* O*/           "V4",    nullptr,   "%@,S,V,",        "FIU,S,F,I",      EShLangAll,   true },
828         { "GatherRed",       /* O, status*/   "V4",    nullptr,   "%@,S,V,,>S",     "FIU,S,F,I,U",    EShLangAll,   true },
829         { "GatherRed",       /* O-4 */        "V4",    nullptr,   "%@,S,V,,,,",     "FIU,S,F,I,,,",   EShLangAll,   true },
830         { "GatherRed",       /* O-4, status */"V4",    nullptr,   "%@,S,V,,,,,S",   "FIU,S,F,I,,,,U", EShLangAll,   true },
831
832         { "GatherGreen",     /*!O*/           "V4",    nullptr,   "%@,S,V",         "FIU,S,F",        EShLangAll,   true },
833         { "GatherGreen",     /* O*/           "V4",    nullptr,   "%@,S,V,",        "FIU,S,F,I",      EShLangAll,   true },
834         { "GatherGreen",     /* O, status*/   "V4",    nullptr,   "%@,S,V,,>S",     "FIU,S,F,I,U",    EShLangAll,   true },
835         { "GatherGreen",     /* O-4 */        "V4",    nullptr,   "%@,S,V,,,,",     "FIU,S,F,I,,,",   EShLangAll,   true },
836         { "GatherGreen",     /* O-4, status */"V4",    nullptr,   "%@,S,V,,,,,S",   "FIU,S,F,I,,,,U", EShLangAll,   true },
837
838         { "GatherBlue",      /*!O*/           "V4",    nullptr,   "%@,S,V",         "FIU,S,F",        EShLangAll,   true },
839         { "GatherBlue",      /* O*/           "V4",    nullptr,   "%@,S,V,",        "FIU,S,F,I",      EShLangAll,   true },
840         { "GatherBlue",      /* O, status*/   "V4",    nullptr,   "%@,S,V,,>S",     "FIU,S,F,I,U",    EShLangAll,   true },
841         { "GatherBlue",      /* O-4 */        "V4",    nullptr,   "%@,S,V,,,,",     "FIU,S,F,I,,,",   EShLangAll,   true },
842         { "GatherBlue",      /* O-4, status */"V4",    nullptr,   "%@,S,V,,,,,S",   "FIU,S,F,I,,,,U", EShLangAll,   true },
843
844         { "GatherAlpha",     /*!O*/           "V4",    nullptr,   "%@,S,V",         "FIU,S,F",        EShLangAll,   true },
845         { "GatherAlpha",     /* O*/           "V4",    nullptr,   "%@,S,V,",        "FIU,S,F,I",      EShLangAll,   true },
846         { "GatherAlpha",     /* O, status*/   "V4",    nullptr,   "%@,S,V,,>S",     "FIU,S,F,I,U",    EShLangAll,   true },
847         { "GatherAlpha",     /* O-4 */        "V4",    nullptr,   "%@,S,V,,,,",     "FIU,S,F,I,,,",   EShLangAll,   true },
848         { "GatherAlpha",     /* O-4, status */"V4",    nullptr,   "%@,S,V,,,,,S",   "FIU,S,F,I,,,,U", EShLangAll,   true },
849
850         { "GatherCmp",       /*!O*/           "V4",    nullptr,   "%@,S,V,S",       "FIU,s,F,",       EShLangAll,   true },
851         { "GatherCmp",       /* O*/           "V4",    nullptr,   "%@,S,V,S,V",     "FIU,s,F,,I",     EShLangAll,   true },
852         { "GatherCmp",       /* O, status*/   "V4",    nullptr,   "%@,S,V,S,V,>S",  "FIU,s,F,,I,U",   EShLangAll,   true },
853         { "GatherCmp",       /* O-4 */        "V4",    nullptr,   "%@,S,V,S,V,,,",  "FIU,s,F,,I,,,",  EShLangAll,   true },
854         { "GatherCmp",       /* O-4, status */"V4",    nullptr,   "%@,S,V,S,V,,V,S","FIU,s,F,,I,,,,U",EShLangAll,   true },
855
856         { "GatherCmpRed",    /*!O*/           "V4",    nullptr,   "%@,S,V,S",       "FIU,s,F,",       EShLangAll,   true },
857         { "GatherCmpRed",    /* O*/           "V4",    nullptr,   "%@,S,V,S,V",     "FIU,s,F,,I",     EShLangAll,   true },
858         { "GatherCmpRed",    /* O, status*/   "V4",    nullptr,   "%@,S,V,S,V,>S",  "FIU,s,F,,I,U",   EShLangAll,   true },
859         { "GatherCmpRed",    /* O-4 */        "V4",    nullptr,   "%@,S,V,S,V,,,",  "FIU,s,F,,I,,,",  EShLangAll,   true },
860         { "GatherCmpRed",    /* O-4, status */"V4",    nullptr,   "%@,S,V,S,V,,V,S","FIU,s,F,,I,,,,U",EShLangAll,   true },
861
862         { "GatherCmpGreen",  /*!O*/           "V4",    nullptr,   "%@,S,V,S",       "FIU,s,F,",       EShLangAll,   true },
863         { "GatherCmpGreen",  /* O*/           "V4",    nullptr,   "%@,S,V,S,V",     "FIU,s,F,,I",     EShLangAll,   true },
864         { "GatherCmpGreen",  /* O, status*/   "V4",    nullptr,   "%@,S,V,S,V,>S",  "FIU,s,F,,I,U",   EShLangAll,   true },
865         { "GatherCmpGreen",  /* O-4 */        "V4",    nullptr,   "%@,S,V,S,V,,,",  "FIU,s,F,,I,,,",  EShLangAll,   true },
866         { "GatherCmpGreen",  /* O-4, status */"V4",    nullptr,   "%@,S,V,S,V,,,,S","FIU,s,F,,I,,,,U",EShLangAll,   true },
867
868         { "GatherCmpBlue",   /*!O*/           "V4",    nullptr,   "%@,S,V,S",       "FIU,s,F,",       EShLangAll,   true },
869         { "GatherCmpBlue",   /* O*/           "V4",    nullptr,   "%@,S,V,S,V",     "FIU,s,F,,I",     EShLangAll,   true },
870         { "GatherCmpBlue",   /* O, status*/   "V4",    nullptr,   "%@,S,V,S,V,>S",  "FIU,s,F,,I,U",   EShLangAll,   true },
871         { "GatherCmpBlue",   /* O-4 */        "V4",    nullptr,   "%@,S,V,S,V,,,",  "FIU,s,F,,I,,,",  EShLangAll,   true },
872         { "GatherCmpBlue",   /* O-4, status */"V4",    nullptr,   "%@,S,V,S,V,,,,S","FIU,s,F,,I,,,,U",EShLangAll,   true },
873
874         { "GatherCmpAlpha",  /*!O*/           "V4",    nullptr,   "%@,S,V,S",       "FIU,s,F,",       EShLangAll,   true },
875         { "GatherCmpAlpha",  /* O*/           "V4",    nullptr,   "%@,S,V,S,V",     "FIU,s,F,,I",     EShLangAll,   true },
876         { "GatherCmpAlpha",  /* O, status*/   "V4",    nullptr,   "%@,S,V,S,V,>S",  "FIU,s,F,,I,U",   EShLangAll,   true },
877         { "GatherCmpAlpha",  /* O-4 */        "V4",    nullptr,   "%@,S,V,S,V,,,",  "FIU,s,F,,I,,,",  EShLangAll,   true },
878         { "GatherCmpAlpha",  /* O-4, status */"V4",    nullptr,   "%@,S,V,S,V,,,,S","FIU,s,F,,I,,,,U",EShLangAll,   true },
879
880         // geometry methods
881         { "Append",                           "-",     "-",       "-",              "-",              EShLangGS ,   true },
882         { "RestartStrip",                     "-",     "-",       "-",              "-",              EShLangGS ,   true },
883
884         // Methods for structurebuffers.  TODO: wildcard type matching.
885         { "Load",                             nullptr, nullptr,   "-",              "-",              EShLangAll,   true },
886         { "Load2",                            nullptr, nullptr,   "-",              "-",              EShLangAll,   true },
887         { "Load3",                            nullptr, nullptr,   "-",              "-",              EShLangAll,   true },
888         { "Load4",                            nullptr, nullptr,   "-",              "-",              EShLangAll,   true },
889         { "Store",                            nullptr, nullptr,   "-",              "-",              EShLangAll,   true },
890         { "Store2",                           nullptr, nullptr,   "-",              "-",              EShLangAll,   true },
891         { "Store3",                           nullptr, nullptr,   "-",              "-",              EShLangAll,   true },
892         { "Store4",                           nullptr, nullptr,   "-",              "-",              EShLangAll,   true },
893         { "GetDimensions",                    nullptr, nullptr,   "-",              "-",              EShLangAll,   true },
894         { "InterlockedAdd",                   nullptr, nullptr,   "-",              "-",              EShLangAll,   true },
895         { "InterlockedAnd",                   nullptr, nullptr,   "-",              "-",              EShLangAll,   true },
896         { "InterlockedCompareExchange",       nullptr, nullptr,   "-",              "-",              EShLangAll,   true },
897         { "InterlockedCompareStore",          nullptr, nullptr,   "-",              "-",              EShLangAll,   true },
898         { "InterlockedExchange",              nullptr, nullptr,   "-",              "-",              EShLangAll,   true },
899         { "InterlockedMax",                   nullptr, nullptr,   "-",              "-",              EShLangAll,   true },
900         { "InterlockedMin",                   nullptr, nullptr,   "-",              "-",              EShLangAll,   true },
901         { "InterlockedOr",                    nullptr, nullptr,   "-",              "-",              EShLangAll,   true },
902         { "InterlockedXor",                   nullptr, nullptr,   "-",              "-",              EShLangAll,   true },
903         { "IncrementCounter",                 nullptr, nullptr,   "-",              "-",              EShLangAll,   true },
904         { "DecrementCounter",                 nullptr, nullptr,   "-",              "-",              EShLangAll,   true },
905         { "Consume",                          nullptr, nullptr,   "-",              "-",              EShLangAll,   true },
906
907         // SM 6.0
908
909         { "WaveIsFirstLane",                  "S",     "B",       "-",              "-",              EShLangPSCS,  false},
910         { "WaveGetLaneCount",                 "S",     "U",       "-",              "-",              EShLangPSCS,  false},
911         { "WaveGetLaneIndex",                 "S",     "U",       "-",              "-",              EShLangPSCS,  false},
912         { "WaveActiveAnyTrue",                "S",     "B",       "S",              "B",              EShLangPSCS,  false},
913         { "WaveActiveAllTrue",                "S",     "B",       "S",              "B",              EShLangPSCS,  false},
914         { "WaveActiveBallot",                 "V4",    "U",       "S",              "B",              EShLangPSCS,  false},
915         { "WaveReadLaneAt",                   nullptr, nullptr,   "SV,S",           "DFUI,U",         EShLangPSCS,  false},
916         { "WaveReadLaneFirst",                nullptr, nullptr,   "SV",             "DFUI",           EShLangPSCS,  false},
917         { "WaveActiveAllEqual",               "S",     "B",       "SV",             "DFUI",           EShLangPSCS,  false},
918         { "WaveActiveAllEqualBool",           "S",     "B",       "S",              "B",              EShLangPSCS,  false},
919         { "WaveActiveCountBits",              "S",     "U",       "S",              "B",              EShLangPSCS,  false},
920         
921         { "WaveActiveSum",                    nullptr, nullptr,   "SV",             "DFUI",           EShLangPSCS,  false},
922         { "WaveActiveProduct",                nullptr, nullptr,   "SV",             "DFUI",           EShLangPSCS,  false},
923         { "WaveActiveBitAnd",                 nullptr, nullptr,   "SV",             "DFUI",           EShLangPSCS,  false},
924         { "WaveActiveBitOr",                  nullptr, nullptr,   "SV",             "DFUI",           EShLangPSCS,  false},
925         { "WaveActiveBitXor",                 nullptr, nullptr,   "SV",             "DFUI",           EShLangPSCS,  false},
926         { "WaveActiveMin",                    nullptr, nullptr,   "SV",             "DFUI",           EShLangPSCS,  false},
927         { "WaveActiveMax",                    nullptr, nullptr,   "SV",             "DFUI",           EShLangPSCS,  false},
928         { "WavePrefixSum",                    nullptr, nullptr,   "SV",             "DFUI",           EShLangPSCS,  false},
929         { "WavePrefixProduct",                nullptr, nullptr,   "SV",             "DFUI",           EShLangPSCS,  false},
930         { "WavePrefixCountBits",              "S",     "U",       "S",              "B",              EShLangPSCS,  false},
931         { "QuadReadAcrossX",                  nullptr, nullptr,   "SV",             "DFUI",           EShLangPSCS,  false},
932         { "QuadReadAcrossY",                  nullptr, nullptr,   "SV",             "DFUI",           EShLangPSCS,  false},
933         { "QuadReadAcrossDiagonal",           nullptr, nullptr,   "SV",             "DFUI",           EShLangPSCS,  false},
934         { "QuadReadLaneAt",                   nullptr, nullptr,   "SV,S",           "DFUI,U",         EShLangPSCS,  false},
935
936         // Methods for subpass input objects
937         { "SubpassLoad",                      "V4",    nullptr,   "[",              "FIU",            EShLangPS,    true },
938         { "SubpassLoad",                      "V4",    nullptr,   "],S",            "FIU,I",          EShLangPS,    true },
939
940         // Mark end of list, since we want to avoid a range-based for, as some compilers don't handle it yet.
941         { nullptr,                            nullptr, nullptr,   nullptr,      nullptr,  0, false },
942     };
943
944     // Create prototypes for the intrinsics.  TODO: Avoid ranged based for until all compilers can handle it.
945     for (int icount = 0; hlslIntrinsics[icount].name; ++icount) {
946         const auto& intrinsic = hlslIntrinsics[icount];
947
948         for (int stage = 0; stage < EShLangCount; ++stage) {                                // for each stage...
949             if ((intrinsic.stage & (1<<stage)) == 0) // skip inapplicable stages
950                 continue;
951
952             // reference to either the common builtins, or stage specific builtins.
953             TString& s = (intrinsic.stage == EShLangAll) ? commonBuiltins : stageBuiltins[stage];
954
955             for (const char* argOrder = intrinsic.argOrder; !IsEndOfArg(argOrder); ++argOrder) { // for each order...
956                 const bool isTexture   = IsTextureType(*argOrder);
957                 const bool isArrayed   = IsArrayed(*argOrder);
958                 const bool isMS        = IsTextureMS(*argOrder);
959                 const bool isBuffer    = IsBuffer(*argOrder);
960                 const bool isImage     = IsImage(*argOrder);
961                 const bool mipInCoord  = HasMipInCoord(intrinsic.name, isMS, isBuffer, isImage);
962                 const int fixedVecSize = FixedVecSize(argOrder);
963                 const int coordArg     = CoordinateArgPos(intrinsic.name, isTexture);
964
965                 // calculate min and max vector and matrix dimensions
966                 int dim0Min = 1;
967                 int dim0Max = 1;
968                 int dim1Min = 1;
969                 int dim1Max = 1;
970
971                 FindVectorMatrixBounds(argOrder, fixedVecSize, dim0Min, dim0Max, dim1Min, dim1Max);
972
973                 for (const char* argType = intrinsic.argType; !IsEndOfArg(argType); ++argType) { // for each type...
974                     for (int dim0 = dim0Min; dim0 <= dim0Max; ++dim0) {          // for each dim 0...
975                         for (int dim1 = dim1Min; dim1 <= dim1Max; ++dim1) {      // for each dim 1...
976                             const char* retOrder = intrinsic.retOrder ? intrinsic.retOrder : argOrder;
977                             const char* retType  = intrinsic.retType  ? intrinsic.retType  : argType;
978
979                             if (!IsValid(intrinsic.name, *retOrder, *retType, *argOrder, *argType, dim0, dim1))
980                                 continue;
981
982                             // Reject some forms of sample methods that don't exist.
983                             if (isTexture && IsIllegalSample(intrinsic.name, argOrder, dim0))
984                                 continue;
985
986                             AppendTypeName(s, retOrder, retType, dim0, dim1);  // add return type
987                             s.append(" ");                                     // space between type and name
988
989                             // methods have a prefix.  TODO: it would be better as an invalid identifier character,
990                             // but that requires a scanner change.
991                             if (intrinsic.method)
992                                 s.append(BUILTIN_PREFIX);
993
994                             s.append(intrinsic.name);                          // intrinsic name
995                             s.append("(");                                     // open paren
996
997                             const char* prevArgOrder = nullptr;
998                             const char* prevArgType = nullptr;
999
1000                             // Append argument types, if any.
1001                             for (int arg = 0; ; ++arg) {
1002                                 const char* nthArgOrder(NthArg(argOrder, arg));
1003                                 const char* nthArgType(NthArg(argType, arg));
1004
1005                                 if (nthArgOrder == nullptr || nthArgType == nullptr)
1006                                     break;
1007
1008                                 // cube textures use vec3 coordinates
1009                                 int argDim0 = isTexture && arg > 0 ? std::min(dim0, 3) : dim0;
1010
1011                                 s.append(arg > 0 ? ", ": "");  // comma separator if needed
1012
1013                                 const char* orderBegin = nthArgOrder;
1014                                 nthArgOrder = IoParam(s, nthArgOrder);
1015
1016                                 // Comma means use the previous argument order and type.
1017                                 HandleRepeatArg(nthArgOrder, prevArgOrder, orderBegin);
1018                                 HandleRepeatArg(nthArgType,  prevArgType, nthArgType);
1019
1020                                 // In case the repeated arg has its own I/O marker
1021                                 nthArgOrder = IoParam(s, nthArgOrder);
1022
1023                                 // arrayed textures have one extra coordinate dimension, except for
1024                                 // the CalculateLevelOfDetail family.
1025                                 if (isArrayed && arg == coordArg && !NoArrayCoord(intrinsic.name))
1026                                     argDim0++;
1027
1028                                 // Some texture methods use an addition arg dimension to hold mip
1029                                 if (arg == coordArg && mipInCoord)
1030                                     argDim0++;
1031
1032                                 // For textures, the 1D case isn't a 1-vector, but a scalar.
1033                                 if (isTexture && argDim0 == 1 && arg > 0 && *nthArgOrder == 'V')
1034                                     nthArgOrder = "S";
1035
1036                                 AppendTypeName(s, nthArgOrder, nthArgType, argDim0, dim1); // Add arguments
1037                             }
1038
1039                             s.append(");\n");            // close paren and trailing semicolon
1040                         } // dim 1 loop
1041                     } // dim 0 loop
1042                 } // arg type loop
1043
1044                 // skip over special characters
1045                 if (isTexture && isalpha(argOrder[1]))
1046                     ++argOrder;
1047                 if (isdigit(argOrder[1]))
1048                     ++argOrder;
1049             } // arg order loop
1050
1051             if (intrinsic.stage == EShLangAll) // common builtins are only added once.
1052                 break;
1053         }
1054     }
1055
1056     createMatTimesMat(); // handle this case separately, for convenience
1057
1058     // printf("Common:\n%s\n",   getCommonString().c_str());
1059     // printf("Frag:\n%s\n",     getStageString(EShLangFragment).c_str());
1060     // printf("Vertex:\n%s\n",   getStageString(EShLangVertex).c_str());
1061     // printf("Geo:\n%s\n",      getStageString(EShLangGeometry).c_str());
1062     // printf("TessCtrl:\n%s\n", getStageString(EShLangTessControl).c_str());
1063     // printf("TessEval:\n%s\n", getStageString(EShLangTessEvaluation).c_str());
1064     // printf("Compute:\n%s\n",  getStageString(EShLangCompute).c_str());
1065 }
1066
1067 //
1068 // Add context-dependent built-in functions and variables that are present
1069 // for the given version and profile.  All the results are put into just the
1070 // commonBuiltins, because it is called for just a specific stage.  So,
1071 // add stage-specific entries to the commonBuiltins, and only if that stage
1072 // was requested.
1073 //
1074 void TBuiltInParseablesHlsl::initialize(const TBuiltInResource& /*resources*/, int /*version*/, EProfile /*profile*/,
1075                                         const SpvVersion& /*spvVersion*/, EShLanguage /*language*/)
1076 {
1077 }
1078
1079 //
1080 // Finish adding/processing context-independent built-in symbols.
1081 // 1) Programmatically add symbols that could not be added by simple text strings above.
1082 // 2) Map built-in functions to operators, for those that will turn into an operation node
1083 //    instead of remaining a function call.
1084 // 3) Tag extension-related symbols added to their base version with their extensions, so
1085 //    that if an early version has the extension turned off, there is an error reported on use.
1086 //
1087 void TBuiltInParseablesHlsl::identifyBuiltIns(int /*version*/, EProfile /*profile*/, const SpvVersion& /*spvVersion*/, EShLanguage /*language*/,
1088                                               TSymbolTable& symbolTable)
1089 {
1090     // symbolTable.relateToOperator("abort",                       EOpAbort);
1091     symbolTable.relateToOperator("abs",                         EOpAbs);
1092     symbolTable.relateToOperator("acos",                        EOpAcos);
1093     symbolTable.relateToOperator("all",                         EOpAll);
1094     symbolTable.relateToOperator("AllMemoryBarrier",            EOpMemoryBarrier);
1095     symbolTable.relateToOperator("AllMemoryBarrierWithGroupSync", EOpAllMemoryBarrierWithGroupSync);
1096     symbolTable.relateToOperator("any",                         EOpAny);
1097     symbolTable.relateToOperator("asdouble",                    EOpAsDouble);
1098     symbolTable.relateToOperator("asfloat",                     EOpIntBitsToFloat);
1099     symbolTable.relateToOperator("asin",                        EOpAsin);
1100     symbolTable.relateToOperator("asint",                       EOpFloatBitsToInt);
1101     symbolTable.relateToOperator("asuint",                      EOpFloatBitsToUint);
1102     symbolTable.relateToOperator("atan",                        EOpAtan);
1103     symbolTable.relateToOperator("atan2",                       EOpAtan);
1104     symbolTable.relateToOperator("ceil",                        EOpCeil);
1105     // symbolTable.relateToOperator("CheckAccessFullyMapped");
1106     symbolTable.relateToOperator("clamp",                       EOpClamp);
1107     symbolTable.relateToOperator("clip",                        EOpClip);
1108     symbolTable.relateToOperator("cos",                         EOpCos);
1109     symbolTable.relateToOperator("cosh",                        EOpCosh);
1110     symbolTable.relateToOperator("countbits",                   EOpBitCount);
1111     symbolTable.relateToOperator("cross",                       EOpCross);
1112     symbolTable.relateToOperator("D3DCOLORtoUBYTE4",            EOpD3DCOLORtoUBYTE4);
1113     symbolTable.relateToOperator("ddx",                         EOpDPdx);
1114     symbolTable.relateToOperator("ddx_coarse",                  EOpDPdxCoarse);
1115     symbolTable.relateToOperator("ddx_fine",                    EOpDPdxFine);
1116     symbolTable.relateToOperator("ddy",                         EOpDPdy);
1117     symbolTable.relateToOperator("ddy_coarse",                  EOpDPdyCoarse);
1118     symbolTable.relateToOperator("ddy_fine",                    EOpDPdyFine);
1119     symbolTable.relateToOperator("degrees",                     EOpDegrees);
1120     symbolTable.relateToOperator("determinant",                 EOpDeterminant);
1121     symbolTable.relateToOperator("DeviceMemoryBarrier",         EOpDeviceMemoryBarrier);
1122     symbolTable.relateToOperator("DeviceMemoryBarrierWithGroupSync", EOpDeviceMemoryBarrierWithGroupSync);
1123     symbolTable.relateToOperator("distance",                    EOpDistance);
1124     symbolTable.relateToOperator("dot",                         EOpDot);
1125     symbolTable.relateToOperator("dst",                         EOpDst);
1126     // symbolTable.relateToOperator("errorf",                      EOpErrorf);
1127     symbolTable.relateToOperator("EvaluateAttributeAtCentroid", EOpInterpolateAtCentroid);
1128     symbolTable.relateToOperator("EvaluateAttributeAtSample",   EOpInterpolateAtSample);
1129     symbolTable.relateToOperator("EvaluateAttributeSnapped",    EOpEvaluateAttributeSnapped);
1130     symbolTable.relateToOperator("exp",                         EOpExp);
1131     symbolTable.relateToOperator("exp2",                        EOpExp2);
1132     symbolTable.relateToOperator("f16tof32",                    EOpF16tof32);
1133     symbolTable.relateToOperator("f32tof16",                    EOpF32tof16);
1134     symbolTable.relateToOperator("faceforward",                 EOpFaceForward);
1135     symbolTable.relateToOperator("firstbithigh",                EOpFindMSB);
1136     symbolTable.relateToOperator("firstbitlow",                 EOpFindLSB);
1137     symbolTable.relateToOperator("floor",                       EOpFloor);
1138     symbolTable.relateToOperator("fma",                         EOpFma);
1139     symbolTable.relateToOperator("fmod",                        EOpMod);
1140     symbolTable.relateToOperator("frac",                        EOpFract);
1141     symbolTable.relateToOperator("frexp",                       EOpFrexp);
1142     symbolTable.relateToOperator("fwidth",                      EOpFwidth);
1143     // symbolTable.relateToOperator("GetRenderTargetSampleCount");
1144     // symbolTable.relateToOperator("GetRenderTargetSamplePosition");
1145     symbolTable.relateToOperator("GroupMemoryBarrier",          EOpWorkgroupMemoryBarrier);
1146     symbolTable.relateToOperator("GroupMemoryBarrierWithGroupSync", EOpWorkgroupMemoryBarrierWithGroupSync);
1147     symbolTable.relateToOperator("InterlockedAdd",              EOpInterlockedAdd);
1148     symbolTable.relateToOperator("InterlockedAnd",              EOpInterlockedAnd);
1149     symbolTable.relateToOperator("InterlockedCompareExchange",  EOpInterlockedCompareExchange);
1150     symbolTable.relateToOperator("InterlockedCompareStore",     EOpInterlockedCompareStore);
1151     symbolTable.relateToOperator("InterlockedExchange",         EOpInterlockedExchange);
1152     symbolTable.relateToOperator("InterlockedMax",              EOpInterlockedMax);
1153     symbolTable.relateToOperator("InterlockedMin",              EOpInterlockedMin);
1154     symbolTable.relateToOperator("InterlockedOr",               EOpInterlockedOr);
1155     symbolTable.relateToOperator("InterlockedXor",              EOpInterlockedXor);
1156     symbolTable.relateToOperator("isfinite",                    EOpIsFinite);
1157     symbolTable.relateToOperator("isinf",                       EOpIsInf);
1158     symbolTable.relateToOperator("isnan",                       EOpIsNan);
1159     symbolTable.relateToOperator("ldexp",                       EOpLdexp);
1160     symbolTable.relateToOperator("length",                      EOpLength);
1161     symbolTable.relateToOperator("lerp",                        EOpMix);
1162     symbolTable.relateToOperator("lit",                         EOpLit);
1163     symbolTable.relateToOperator("log",                         EOpLog);
1164     symbolTable.relateToOperator("log10",                       EOpLog10);
1165     symbolTable.relateToOperator("log2",                        EOpLog2);
1166     symbolTable.relateToOperator("mad",                         EOpFma);
1167     symbolTable.relateToOperator("max",                         EOpMax);
1168     symbolTable.relateToOperator("min",                         EOpMin);
1169     symbolTable.relateToOperator("modf",                        EOpModf);
1170     // symbolTable.relateToOperator("msad4",                       EOpMsad4);
1171     symbolTable.relateToOperator("mul",                         EOpGenMul);
1172     // symbolTable.relateToOperator("noise",                    EOpNoise); // TODO: check return type
1173     symbolTable.relateToOperator("normalize",                   EOpNormalize);
1174     symbolTable.relateToOperator("pow",                         EOpPow);
1175     // symbolTable.relateToOperator("printf",                     EOpPrintf);
1176     // symbolTable.relateToOperator("Process2DQuadTessFactorsAvg");
1177     // symbolTable.relateToOperator("Process2DQuadTessFactorsMax");
1178     // symbolTable.relateToOperator("Process2DQuadTessFactorsMin");
1179     // symbolTable.relateToOperator("ProcessIsolineTessFactors");
1180     // symbolTable.relateToOperator("ProcessQuadTessFactorsAvg");
1181     // symbolTable.relateToOperator("ProcessQuadTessFactorsMax");
1182     // symbolTable.relateToOperator("ProcessQuadTessFactorsMin");
1183     // symbolTable.relateToOperator("ProcessTriTessFactorsAvg");
1184     // symbolTable.relateToOperator("ProcessTriTessFactorsMax");
1185     // symbolTable.relateToOperator("ProcessTriTessFactorsMin");
1186     symbolTable.relateToOperator("radians",                     EOpRadians);
1187     symbolTable.relateToOperator("rcp",                         EOpRcp);
1188     symbolTable.relateToOperator("reflect",                     EOpReflect);
1189     symbolTable.relateToOperator("refract",                     EOpRefract);
1190     symbolTable.relateToOperator("reversebits",                 EOpBitFieldReverse);
1191     symbolTable.relateToOperator("round",                       EOpRoundEven);
1192     symbolTable.relateToOperator("rsqrt",                       EOpInverseSqrt);
1193     symbolTable.relateToOperator("saturate",                    EOpSaturate);
1194     symbolTable.relateToOperator("sign",                        EOpSign);
1195     symbolTable.relateToOperator("sin",                         EOpSin);
1196     symbolTable.relateToOperator("sincos",                      EOpSinCos);
1197     symbolTable.relateToOperator("sinh",                        EOpSinh);
1198     symbolTable.relateToOperator("smoothstep",                  EOpSmoothStep);
1199     symbolTable.relateToOperator("sqrt",                        EOpSqrt);
1200     symbolTable.relateToOperator("step",                        EOpStep);
1201     symbolTable.relateToOperator("tan",                         EOpTan);
1202     symbolTable.relateToOperator("tanh",                        EOpTanh);
1203     symbolTable.relateToOperator("tex1D",                       EOpTexture);
1204     symbolTable.relateToOperator("tex1Dbias",                   EOpTextureBias);
1205     symbolTable.relateToOperator("tex1Dgrad",                   EOpTextureGrad);
1206     symbolTable.relateToOperator("tex1Dlod",                    EOpTextureLod);
1207     symbolTable.relateToOperator("tex1Dproj",                   EOpTextureProj);
1208     symbolTable.relateToOperator("tex2D",                       EOpTexture);
1209     symbolTable.relateToOperator("tex2Dbias",                   EOpTextureBias);
1210     symbolTable.relateToOperator("tex2Dgrad",                   EOpTextureGrad);
1211     symbolTable.relateToOperator("tex2Dlod",                    EOpTextureLod);
1212     symbolTable.relateToOperator("tex2Dproj",                   EOpTextureProj);
1213     symbolTable.relateToOperator("tex3D",                       EOpTexture);
1214     symbolTable.relateToOperator("tex3Dbias",                   EOpTextureBias);
1215     symbolTable.relateToOperator("tex3Dgrad",                   EOpTextureGrad);
1216     symbolTable.relateToOperator("tex3Dlod",                    EOpTextureLod);
1217     symbolTable.relateToOperator("tex3Dproj",                   EOpTextureProj);
1218     symbolTable.relateToOperator("texCUBE",                     EOpTexture);
1219     symbolTable.relateToOperator("texCUBEbias",                 EOpTextureBias);
1220     symbolTable.relateToOperator("texCUBEgrad",                 EOpTextureGrad);
1221     symbolTable.relateToOperator("texCUBElod",                  EOpTextureLod);
1222     symbolTable.relateToOperator("texCUBEproj",                 EOpTextureProj);
1223     symbolTable.relateToOperator("transpose",                   EOpTranspose);
1224     symbolTable.relateToOperator("trunc",                       EOpTrunc);
1225
1226     // Texture methods
1227     symbolTable.relateToOperator(BUILTIN_PREFIX "Sample",                      EOpMethodSample);
1228     symbolTable.relateToOperator(BUILTIN_PREFIX "SampleBias",                  EOpMethodSampleBias);
1229     symbolTable.relateToOperator(BUILTIN_PREFIX "SampleCmp",                   EOpMethodSampleCmp);
1230     symbolTable.relateToOperator(BUILTIN_PREFIX "SampleCmpLevelZero",          EOpMethodSampleCmpLevelZero);
1231     symbolTable.relateToOperator(BUILTIN_PREFIX "SampleGrad",                  EOpMethodSampleGrad);
1232     symbolTable.relateToOperator(BUILTIN_PREFIX "SampleLevel",                 EOpMethodSampleLevel);
1233     symbolTable.relateToOperator(BUILTIN_PREFIX "Load",                        EOpMethodLoad);
1234     symbolTable.relateToOperator(BUILTIN_PREFIX "GetDimensions",               EOpMethodGetDimensions);
1235     symbolTable.relateToOperator(BUILTIN_PREFIX "GetSamplePosition",           EOpMethodGetSamplePosition);
1236     symbolTable.relateToOperator(BUILTIN_PREFIX "Gather",                      EOpMethodGather);
1237     symbolTable.relateToOperator(BUILTIN_PREFIX "CalculateLevelOfDetail",      EOpMethodCalculateLevelOfDetail);
1238     symbolTable.relateToOperator(BUILTIN_PREFIX "CalculateLevelOfDetailUnclamped", EOpMethodCalculateLevelOfDetailUnclamped);
1239
1240     // Structure buffer methods (excluding associations already made above for texture methods w/ same name)
1241     symbolTable.relateToOperator(BUILTIN_PREFIX "Load2",                       EOpMethodLoad2);
1242     symbolTable.relateToOperator(BUILTIN_PREFIX "Load3",                       EOpMethodLoad3);
1243     symbolTable.relateToOperator(BUILTIN_PREFIX "Load4",                       EOpMethodLoad4);
1244     symbolTable.relateToOperator(BUILTIN_PREFIX "Store",                       EOpMethodStore);
1245     symbolTable.relateToOperator(BUILTIN_PREFIX "Store2",                      EOpMethodStore2);
1246     symbolTable.relateToOperator(BUILTIN_PREFIX "Store3",                      EOpMethodStore3);
1247     symbolTable.relateToOperator(BUILTIN_PREFIX "Store4",                      EOpMethodStore4);
1248     symbolTable.relateToOperator(BUILTIN_PREFIX "IncrementCounter",            EOpMethodIncrementCounter);
1249     symbolTable.relateToOperator(BUILTIN_PREFIX "DecrementCounter",            EOpMethodDecrementCounter);
1250     // Append is also a GS method: we don't add it twice
1251     symbolTable.relateToOperator(BUILTIN_PREFIX "Consume",                     EOpMethodConsume);
1252
1253     symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedAdd",              EOpInterlockedAdd);
1254     symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedAnd",              EOpInterlockedAnd);
1255     symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedCompareExchange",  EOpInterlockedCompareExchange);
1256     symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedCompareStore",     EOpInterlockedCompareStore);
1257     symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedExchange",         EOpInterlockedExchange);
1258     symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedMax",              EOpInterlockedMax);
1259     symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedMin",              EOpInterlockedMin);
1260     symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedOr",               EOpInterlockedOr);
1261     symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedXor",              EOpInterlockedXor);
1262
1263     // SM5 Texture methods
1264     symbolTable.relateToOperator(BUILTIN_PREFIX "GatherRed",                   EOpMethodGatherRed);
1265     symbolTable.relateToOperator(BUILTIN_PREFIX "GatherGreen",                 EOpMethodGatherGreen);
1266     symbolTable.relateToOperator(BUILTIN_PREFIX "GatherBlue",                  EOpMethodGatherBlue);
1267     symbolTable.relateToOperator(BUILTIN_PREFIX "GatherAlpha",                 EOpMethodGatherAlpha);
1268     symbolTable.relateToOperator(BUILTIN_PREFIX "GatherCmp",                   EOpMethodGatherCmpRed); // alias
1269     symbolTable.relateToOperator(BUILTIN_PREFIX "GatherCmpRed",                EOpMethodGatherCmpRed);
1270     symbolTable.relateToOperator(BUILTIN_PREFIX "GatherCmpGreen",              EOpMethodGatherCmpGreen);
1271     symbolTable.relateToOperator(BUILTIN_PREFIX "GatherCmpBlue",               EOpMethodGatherCmpBlue);
1272     symbolTable.relateToOperator(BUILTIN_PREFIX "GatherCmpAlpha",              EOpMethodGatherCmpAlpha);
1273
1274     // GS methods
1275     symbolTable.relateToOperator(BUILTIN_PREFIX "Append",                      EOpMethodAppend);
1276     symbolTable.relateToOperator(BUILTIN_PREFIX "RestartStrip",                EOpMethodRestartStrip);
1277
1278     // Wave ops
1279     symbolTable.relateToOperator("WaveIsFirstLane",                            EOpSubgroupElect);
1280     symbolTable.relateToOperator("WaveGetLaneCount",                           EOpWaveGetLaneCount);
1281     symbolTable.relateToOperator("WaveGetLaneIndex",                           EOpWaveGetLaneIndex);
1282     symbolTable.relateToOperator("WaveActiveAnyTrue",                          EOpSubgroupAny);
1283     symbolTable.relateToOperator("WaveActiveAllTrue",                          EOpSubgroupAll);
1284     symbolTable.relateToOperator("WaveActiveBallot",                           EOpSubgroupBallot);
1285     symbolTable.relateToOperator("WaveReadLaneFirst",                          EOpSubgroupBroadcastFirst);
1286     symbolTable.relateToOperator("WaveReadLaneAt",                             EOpSubgroupShuffle);
1287     symbolTable.relateToOperator("WaveActiveAllEqual",                         EOpSubgroupAllEqual);
1288     symbolTable.relateToOperator("WaveActiveAllEqualBool",                     EOpSubgroupAllEqual);
1289     symbolTable.relateToOperator("WaveActiveCountBits",                        EOpWaveActiveCountBits);
1290     symbolTable.relateToOperator("WaveActiveSum",                              EOpSubgroupAdd);
1291     symbolTable.relateToOperator("WaveActiveProduct",                          EOpSubgroupMul);
1292     symbolTable.relateToOperator("WaveActiveBitAnd",                           EOpSubgroupAnd);
1293     symbolTable.relateToOperator("WaveActiveBitOr",                            EOpSubgroupOr);
1294     symbolTable.relateToOperator("WaveActiveBitXor",                           EOpSubgroupXor);
1295     symbolTable.relateToOperator("WaveActiveMin",                              EOpSubgroupMin);
1296     symbolTable.relateToOperator("WaveActiveMax",                              EOpSubgroupMax);
1297     symbolTable.relateToOperator("WavePrefixSum",                              EOpSubgroupInclusiveAdd);
1298     symbolTable.relateToOperator("WavePrefixProduct",                          EOpSubgroupInclusiveMul);
1299     symbolTable.relateToOperator("WavePrefixCountBits",                        EOpWavePrefixCountBits);
1300     symbolTable.relateToOperator("QuadReadAcrossX",                            EOpSubgroupQuadSwapHorizontal);
1301     symbolTable.relateToOperator("QuadReadAcrossY",                            EOpSubgroupQuadSwapVertical);
1302     symbolTable.relateToOperator("QuadReadAcrossDiagonal",                     EOpSubgroupQuadSwapDiagonal);
1303     symbolTable.relateToOperator("QuadReadLaneAt",                             EOpSubgroupQuadBroadcast);
1304
1305     // Subpass input methods
1306     symbolTable.relateToOperator(BUILTIN_PREFIX "SubpassLoad",                 EOpSubpassLoad);
1307     symbolTable.relateToOperator(BUILTIN_PREFIX "SubpassLoadMS",               EOpSubpassLoadMS);
1308 }
1309
1310 //
1311 // Add context-dependent (resource-specific) built-ins not handled by the above.  These
1312 // would be ones that need to be programmatically added because they cannot
1313 // be added by simple text strings.  For these, also
1314 // 1) Map built-in functions to operators, for those that will turn into an operation node
1315 //    instead of remaining a function call.
1316 // 2) Tag extension-related symbols added to their base version with their extensions, so
1317 //    that if an early version has the extension turned off, there is an error reported on use.
1318 //
1319 void TBuiltInParseablesHlsl::identifyBuiltIns(int /*version*/, EProfile /*profile*/, const SpvVersion& /*spvVersion*/, EShLanguage /*language*/,
1320                                               TSymbolTable& /*symbolTable*/, const TBuiltInResource& /*resources*/)
1321 {
1322 }
1323
1324 } // end namespace glslang