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