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 <cctype>
     53 #include <utility>
     54 #include <algorithm>
     55 
     56 namespace {  // anonymous namespace functions
     57 
     58 const bool UseHlslTypes = false;
     59 
     60 const char* BaseTypeName(const char argOrder, const char* scalarName, const char* vecName, const char* matName)
     61 {
     62     switch (argOrder) {
     63     case 'S': return scalarName;
     64     case 'V': return vecName;
     65     case 'M': return matName;
     66     default:  return "UNKNOWN_TYPE";
     67     }
     68 }
     69 
     70 bool IsTextureType(const char argOrder)    { return argOrder == '%' || argOrder == '@'; }
     71 bool IsTextureArrayed(const char argOrder) { return argOrder == '@'; }
     72 bool IsTextureMS(const char /*argOrder*/)      { return false; } // TODO: ...
     73 
     74 // Reject certain combinations that are illegal sample methods.  For example,
     75 // 3D arrays.
     76 bool IsIllegalSample(const glslang::TString& name, const char* argOrder, int dim0)
     77 {
     78     const bool isArrayed = IsTextureArrayed(*argOrder);
     79     const bool isMS      = IsTextureMS(*argOrder);
     80 
     81     // there are no 3D arrayed textures, or 3D SampleCmp
     82     if (dim0 == 3 && (isArrayed || name == "SampleCmp"))
     83         return true;
     84 
     85     const int numArgs = int(std::count(argOrder, argOrder + strlen(argOrder), ',')) + 1;
     86 
     87     // Reject invalid offset arrayed forms with cubemaps
     88     if (isArrayed && dim0 == 4) {
     89         if ((name == "Sample"             && numArgs >= 4) ||
     90             (name == "SampleBias"         && numArgs >= 5) ||
     91             (name == "SampleCmp"          && numArgs >= 5) ||
     92             (name == "SampleCmpLevelZero" && numArgs >= 4) ||
     93             (name == "SampleGrad"         && numArgs >= 6) ||
     94             (name == "SampleLevel"        && numArgs >= 5))
     95             return true;
     96     }
     97 
     98     // Reject invalid Loads
     99     if (name == "Load") {
    100         if ((numArgs >= 3 && !isMS) ||  // Load with sampleindex requires multisample
    101             (dim0 == 4))                // Load does not support any cubemaps, arrayed or not.
    102             return true;
    103     }
    104 
    105     return false;
    106 }
    107 
    108 // Create and return a type name.  This is done in GLSL, not HLSL conventions, until such
    109 // time as builtins are parsed using the HLSL parser.
    110 //
    111 //    order:   S = scalar, V = vector, M = matrix
    112 //    argType: F = float, D = double, I = int, U = uint, B = bool, S = sampler
    113 //    dim0 = vector dimension, or matrix 1st dimension
    114 //    dim1 = matrix 2nd dimension
    115 glslang::TString& AppendTypeName(glslang::TString& s, const char* argOrder, const char* argType, int dim0, int dim1)
    116 {
    117     const bool isTranspose = (argOrder[0] == '^');
    118     const bool isMatMul    = (argOrder[0] == '#');
    119     const bool isTexture   = IsTextureType(argOrder[0]);
    120     const bool isArrayed   = IsTextureArrayed(argOrder[0]);
    121     //const bool isMS        = IsTextureMS(argOrder[0]);
    122 
    123     char order = *argOrder;
    124     char type  = *argType;
    125 
    126     if (isTranspose) {  // Take transpose of matrix dimensions
    127         order = *++argOrder;
    128         std::swap(dim0, dim1);
    129     } else if (isMatMul) {
    130         order = *++argOrder;
    131         dim0 = dim1;    // set vector dimension to mat col
    132     } else if (isTexture) {
    133         order = *++argOrder;
    134         if (type == 'F')       // map base type to texture of that type.
    135             type = 'T';        // e.g, int -> itexture, uint -> utexture, etc.
    136         else if (type == 'I')
    137             type = 'i';
    138         else if (type == 'U')
    139             type = 'u';
    140     }
    141 
    142     if (UseHlslTypes) {
    143         switch (type) {
    144         case '-': s += "void";            break;
    145         case 'F': s += "float";           break;
    146         case 'D': s += "double";          break;
    147         case 'I': s += "int";             break;
    148         case 'U': s += "uint";            break;
    149         case 'B': s += "bool";            break;
    150         case 'S': s += "sampler";         break;
    151         case 'T': s += "Texture";         break;
    152         case 'i': s += "Texture <int4>";  break;
    153         case 'u': s += "Texture <uint4>"; break;
    154         default:  s += "UNKNOWN_TYPE";    break;
    155         }
    156     } else {
    157         switch (type) {
    158         case '-': s += "void"; break;
    159         case 'F': s += BaseTypeName(order, "float",   "vec",     "mat");     break;
    160         case 'D': s += BaseTypeName(order, "double",  "dvec",    "dmat");    break;
    161         case 'I': s += BaseTypeName(order, "int",     "ivec",    "imat");    break;
    162         case 'U': s += BaseTypeName(order, "uint",    "uvec",    "umat");    break;
    163         case 'B': s += BaseTypeName(order, "bool",    "bvec",    "bmat");    break;
    164         case 'S': s += "sampler";                                            break;
    165         case 'T': // fall through
    166         case 'i': // ...
    167         case 'u': // ...
    168             if (type != 'T')
    169                 s += type;
    170 
    171             s += "texture";
    172             break;
    173 
    174         default:  s += "UNKNOWN_TYPE"; break;
    175         }
    176     }
    177 
    178     // handle fixed vector sizes, such as float3, and only ever 3.
    179     const int fixedVecSize = isdigit(argOrder[1]) ? (argOrder[1] - '0') : 0;
    180     if (fixedVecSize != 0)
    181         dim0 = dim1 = fixedVecSize;
    182 
    183     // Add sampler dimensions
    184     if (type == 'S' || isTexture) {
    185         if (order == 'V') {
    186             switch (dim0) {
    187             case 1: s += "1D";   break;
    188             case 2: s += "2D";   break;
    189             case 3: s += "3D";   break;
    190             case 4: s += "Cube"; break;
    191             default: s += "UNKNOWN_SAMPLER"; break;
    192             }
    193         }
    194     } else {
    195         // Non-sampler type:
    196         // verify dimensions
    197         if (((order == 'V' || order == 'M') && (dim0 < 1 || dim0 > 4)) ||
    198             (order == 'M' && (dim1 < 1 || dim1 > 4))) {
    199             s += "UNKNOWN_DIMENSION";
    200             return s;
    201         }
    202 
    203         switch (order) {
    204         case '-': break;  // no dimensions for voids
    205         case 'S': break;  // no dimensions on scalars
    206         case 'V': s += ('0' + char(dim0)); break;
    207         case 'M':
    208             {
    209                 if (!UseHlslTypes)  // GLSL has column first for mat types
    210                     std::swap(dim0, dim1);
    211                 s += ('0' + char(dim0));
    212                 s += 'x';
    213                 s += ('0' + char(dim1));
    214                 break;
    215             }
    216         }
    217     }
    218 
    219     // handle arrayed textures
    220     if (isArrayed)
    221         s += "Array";
    222 
    223     return s;
    224 }
    225 
    226 // TODO: the GLSL parser is currently used to parse HLSL prototypes.  However, many valid HLSL prototypes
    227 // are not valid GLSL prototypes.  This rejects the invalid ones.  Thus, there is a single switch below
    228 // to enable creation of the entire HLSL space.
    229 inline bool IsValidGlsl(const char* cname, char retOrder, char retType, char argOrder, char argType,
    230                         int dim0, int dim1, int dim0Max, int dim1Max)
    231 {
    232     const bool isVec = dim0Max > 1 || argType == 'V';
    233     const bool isMat = dim1Max > 1 || argType == 'M';
    234 
    235     if (!IsTextureType(argOrder) &&
    236         ((isVec && dim0 == 1)            ||  // avoid vec1
    237          (isMat && dim0 == 1 && dim1 == 1)))  // avoid mat1x1
    238         return false;
    239 
    240     const std::string name(cname);  // for ease of comparison. slow, but temporary, until HLSL parser is online.
    241 
    242     if (isMat && dim1 == 1)  // TODO: avoid mat Nx1 until we find the right GLSL profile
    243         return false;
    244 
    245     if ((isMat && (argType == 'I' || argType == 'U' || argType == 'B')) ||
    246         (retOrder == 'M' && (retType == 'I' || retType == 'U' || retType == 'B')))
    247         return false;
    248 
    249     if (name == "GetRenderTargetSamplePosition" ||
    250         name == "tex1D" ||
    251         name == "tex1Dgrad")
    252         return false;
    253 
    254     return true;
    255 }
    256 
    257 
    258 // Return true for the end of a single argument key, which can be the end of the string, or
    259 // the comma separator.
    260 inline bool IsEndOfArg(const char* arg)
    261 {
    262     return arg == nullptr || *arg == '\0' || *arg == ',';
    263 }
    264 
    265 
    266 // return position of end of argument specifier
    267 inline const char* FindEndOfArg(const char* arg)
    268 {
    269     while (!IsEndOfArg(arg))
    270         ++arg;
    271 
    272     return *arg == '\0' ? nullptr : arg;
    273 }
    274 
    275 // If this is a fixed vector size, such as V3, return the size.  Else return 0.
    276 int FixedVecSize(const char* arg)
    277 {
    278     while (!IsEndOfArg(arg)) {
    279         if (isdigit(*arg))
    280             return *arg - '0';
    281         ++arg;
    282     }
    283 
    284     return 0; // none found.
    285 }
    286 
    287 
    288 // Return pointer to beginning of Nth argument specifier in the string.
    289 inline const char* NthArg(const char* arg, int n)
    290 {
    291     for (int x=0; x<n && arg; ++x)
    292         if ((arg = FindEndOfArg(arg)) != nullptr)
    293             ++arg;  // skip arg separator
    294 
    295     return arg;
    296 }
    297 
    298 inline void FindVectorMatrixBounds(const char* argOrder, int fixedVecSize, int& dim0Min, int& dim0Max, int& /*dim1Min*/, int& dim1Max)
    299 {
    300     for (int arg = 0; ; ++arg) {
    301         const char* nthArgOrder(NthArg(argOrder, arg));
    302         if (nthArgOrder == nullptr)
    303             break;
    304         else if (*nthArgOrder == 'V')
    305             dim0Max = 4;
    306         else if (*nthArgOrder == 'M')
    307             dim0Max = dim1Max = 4;
    308     }
    309 
    310     if (fixedVecSize > 0) // handle fixed sized vectors
    311         dim0Min = dim0Max = fixedVecSize;
    312 }
    313 
    314 } // end anonymous namespace
    315 
    316 namespace glslang {
    317 
    318 TBuiltInParseablesHlsl::TBuiltInParseablesHlsl()
    319 {
    320 }
    321 
    322 
    323 //
    324 // Handle creation of mat*mat specially, since it doesn't fall conveniently out of
    325 // the generic prototype creation code below.
    326 //
    327 void TBuiltInParseablesHlsl::createMatTimesMat()
    328 {
    329     TString& s = commonBuiltins;
    330 
    331     const int first = (UseHlslTypes ? 1 : 2);
    332 
    333     for (int xRows = first; xRows <=4; xRows++) {
    334         for (int xCols = first; xCols <=4; xCols++) {
    335             const int yRows = xCols;
    336             for (int yCols = first; yCols <=4; yCols++) {
    337                 const int retRows = xRows;
    338                 const int retCols = yCols;
    339 
    340                 AppendTypeName(s, "M", "F", retRows, retCols);  // add return type
    341                 s.append(" ");                                  // space between type and name
    342                 s.append("mul");                                // intrinsic name
    343                 s.append("(");                                  // open paren
    344 
    345                 AppendTypeName(s, "M", "F", xRows, xCols);      // add X input
    346                 s.append(", ");
    347                 AppendTypeName(s, "M", "F", yRows, yCols);      // add Y input
    348 
    349                 s.append(");\n");                               // close paren
    350             }
    351         }
    352     }
    353 }
    354 
    355 //
    356 // Add all context-independent built-in functions and variables that are present
    357 // for the given version and profile.  Share common ones across stages, otherwise
    358 // make stage-specific entries.
    359 //
    360 // Most built-ins variables can be added as simple text strings.  Some need to
    361 // be added programmatically, which is done later in IdentifyBuiltIns() below.
    362 //
    363 void TBuiltInParseablesHlsl::initialize(int /*version*/, EProfile /*profile*/, const SpvVersion& /*spvVersion*/)
    364 {
    365     static const EShLanguageMask EShLangAll = EShLanguageMask(EShLangCount - 1);
    366 
    367     // This structure encodes the prototype information for each HLSL intrinsic.
    368     // Because explicit enumeration would be cumbersome, it's procedurally generated.
    369     // orderKey can be:
    370     //   S = scalar, V = vector, M = matrix, - = void
    371     // typekey can be:
    372     //   D = double, F = float, U = uint, I = int, B = bool, S = sampler
    373     // An empty order or type key repeats the first one.  E.g: SVM,, means 3 args each of SVM.
    374     // '>' as first letter of order creates an output parameter
    375     // '<' as first letter of order creates an input parameter
    376     // '^' as first letter of order takes transpose dimensions
    377     // '#' as first letter of order sets rows=cols for mats
    378     // '%' as first letter of order creates texture of given F/I/U type (texture, itexture, etc)
    379     // '@' as first letter of order creates arrayed texture of given type
    380 
    381     static const struct {
    382         const char*   name;      // intrinsic name
    383         const char*   retOrder;  // return type key: empty matches order of 1st argument
    384         const char*   retType;   // return type key: empty matches type of 1st argument
    385         const char*   argOrder;  // argument order key
    386         const char*   argType;   // argument type key
    387         unsigned int  stage;     // stage mask
    388     } hlslIntrinsics[] = {
    389         // name                               retOrd   retType    argOrder      argType   stage mask
    390         // -----------------------------------------------------------------------------------------------
    391         { "abort",                            nullptr, nullptr,   "-",          "-",      EShLangAll },
    392         { "abs",                              nullptr, nullptr,   "SVM",        "DFUI",   EShLangAll },
    393         { "acos",                             nullptr, nullptr,   "SVM",        "F",      EShLangAll },
    394         { "all",                              "S",    "B",        "SVM",        "BFI",    EShLangAll },
    395         { "AllMemoryBarrier",                 nullptr, nullptr,   "-",          "-",      EShLangComputeMask },
    396         { "AllMemoryBarrierWithGroupSync",    nullptr, nullptr,   "-",          "-",      EShLangComputeMask },
    397         { "any",                              "S",     "B",       "SVM",        "BFI",    EShLangAll },
    398         { "asdouble",                         "S",     "D",       "S,",         "U,",     EShLangAll },
    399         { "asdouble",                         "V2",    "D",       "V2,",        "U,",     EShLangAll },
    400         { "asfloat",                          nullptr, "F",       "SVM",        "BFIU",   EShLangAll },
    401         { "asin",                             nullptr, nullptr,   "SVM",        "F",      EShLangAll },
    402         { "asint",                            nullptr, "I",       "SVM",        "FU",     EShLangAll },
    403         { "asuint",                           nullptr, "U",       "SVM",        "FU",     EShLangAll },
    404         { "atan",                             nullptr, nullptr,   "SVM",        "F",      EShLangAll },
    405         { "atan2",                            nullptr, nullptr,   "SVM,",       "F,",     EShLangAll },
    406         { "ceil",                             nullptr, nullptr,   "SVM",        "F",      EShLangAll },
    407         { "CheckAccessFullyMapped",           "S",     "B" ,      "S",          "U",      EShLangFragmentMask | EShLangComputeMask },
    408         { "clamp",                            nullptr, nullptr,   "SVM,,",      "FUI,,",  EShLangAll },
    409         { "clip",                             "-",     "-",       "SVM",        "F",      EShLangFragmentMask },
    410         { "cos",                              nullptr, nullptr,   "SVM",        "F",      EShLangAll },
    411         { "cosh",                             nullptr, nullptr,   "SVM",        "F",      EShLangAll },
    412         { "countbits",                        nullptr, nullptr,   "SV",         "U",      EShLangAll },
    413         { "cross",                            nullptr, nullptr,   "V3,",        "F,",     EShLangAll },
    414         { "D3DCOLORtoUBYTE4",                 "V4",    "I",       "V4",         "F",      EShLangAll },
    415         { "ddx",                              nullptr, nullptr,   "SVM",        "F",      EShLangFragmentMask },
    416         { "ddx_coarse",                       nullptr, nullptr,   "SVM",        "F",      EShLangFragmentMask },
    417         { "ddx_fine",                         nullptr, nullptr,   "SVM",        "F",      EShLangFragmentMask },
    418         { "ddy",                              nullptr, nullptr,   "SVM",        "F",      EShLangFragmentMask },
    419         { "ddy_coarse",                       nullptr, nullptr,   "SVM",        "F",      EShLangFragmentMask },
    420         { "ddy_fine",                         nullptr, nullptr,   "SVM",        "F",      EShLangFragmentMask },
    421         { "degrees",                          nullptr, nullptr,   "SVM",        "F",      EShLangAll },
    422         { "determinant",                      "S",     "F",       "M",          "F",      EShLangAll },
    423         { "DeviceMemoryBarrier",              nullptr, nullptr,   "-",          "-",      EShLangFragmentMask | EShLangComputeMask },
    424         { "DeviceMemoryBarrierWithGroupSync", nullptr, nullptr,   "-",          "-",      EShLangComputeMask },
    425         { "distance",                         "S",     "F",       "V,",         "F,",     EShLangAll },
    426         { "dot",                              "S",     nullptr,   "V,",         "FI,",    EShLangAll },
    427         { "dst",                              nullptr, nullptr,   "V4,V4",      "F,",     EShLangAll },
    428         // { "errorf",                           "-",     "-",       "",         "",     EShLangAll }, TODO: varargs
    429         { "EvaluateAttributeAtCentroid",      nullptr, nullptr,   "SVM",        "F",      EShLangFragmentMask },
    430         { "EvaluateAttributeAtSample",        nullptr, nullptr,   "SVM,S",      "F,U",    EShLangFragmentMask },
    431         { "EvaluateAttributeSnapped",         nullptr, nullptr,   "SVM,V2",     "F,I",    EShLangFragmentMask },
    432         { "exp",                              nullptr, nullptr,   "SVM",        "F",      EShLangAll },
    433         { "exp2",                             nullptr, nullptr,   "SVM",        "F",      EShLangAll },
    434         { "f16tof32",                         nullptr, "F",       "SV",         "U",      EShLangAll },
    435         { "f32tof16",                         nullptr, "U",       "SV",         "F",      EShLangAll },
    436         { "faceforward",                      nullptr, nullptr,   "V,,",        "F,,",    EShLangAll },
    437         { "firstbithigh",                     nullptr, nullptr,   "SV",         "UI",     EShLangAll },
    438         { "firstbitlow",                      nullptr, nullptr,   "SV",         "UI",     EShLangAll },
    439         { "floor",                            nullptr, nullptr,   "SVM",        "F",      EShLangAll },
    440         { "fma",                              nullptr, nullptr,   "SVM,,",      "D,,",    EShLangAll },
    441         { "fmod",                             nullptr, nullptr,   "SVM,",       "F,",     EShLangAll },
    442         { "frac",                             nullptr, nullptr,   "SVM",        "F",      EShLangAll },
    443         { "frexp",                            nullptr, nullptr,   "SVM,",       "F,",     EShLangAll },
    444         { "fwidth",                           nullptr, nullptr,   "SVM",        "F",      EShLangFragmentMask },
    445         { "GetRenderTargetSampleCount",       "S",     "U",       "-",          "-",      EShLangAll },
    446         { "GetRenderTargetSamplePosition",    "V2",    "F",       "V1",         "I",      EShLangAll },
    447         { "GroupMemoryBarrier",               nullptr, nullptr,   "-",          "-",      EShLangComputeMask },
    448         { "GroupMemoryBarrierWithGroupSync",  nullptr, nullptr,   "-",          "-",      EShLangComputeMask },
    449         { "InterlockedAdd",                   "-",     "-",       "SVM,,>",     "UI,,",   EShLangFragmentMask | EShLangComputeMask },
    450         { "InterlockedAdd",                   "-",     "-",       "SVM,",       "UI,",    EShLangFragmentMask | EShLangComputeMask },
    451         { "InterlockedAnd",                   "-",     "-",       "SVM,,>",     "UI,,",   EShLangFragmentMask | EShLangComputeMask },
    452         { "InterlockedAnd",                   "-",     "-",       "SVM,",       "UI,",    EShLangFragmentMask | EShLangComputeMask },
    453         { "InterlockedCompareExchange",       "-",     "-",       "SVM,,,>",    "UI,,,",  EShLangFragmentMask | EShLangComputeMask },
    454         { "InterlockedCompareStore",          "-",     "-",       "SVM,,",      "UI,,",   EShLangFragmentMask | EShLangComputeMask },
    455         { "InterlockedExchange",              "-",     "-",       "SVM,,>",     "UI,,",   EShLangFragmentMask | EShLangComputeMask },
    456         { "InterlockedMax",                   "-",     "-",       "SVM,,>",     "UI,,",   EShLangFragmentMask | EShLangComputeMask },
    457         { "InterlockedMax",                   "-",     "-",       "SVM,",       "UI,",    EShLangFragmentMask | EShLangComputeMask },
    458         { "InterlockedMin",                   "-",     "-",       "SVM,,>",     "UI,,",   EShLangFragmentMask | EShLangComputeMask },
    459         { "InterlockedMin",                   "-",     "-",       "SVM,",       "UI,",    EShLangFragmentMask | EShLangComputeMask },
    460         { "InterlockedOr",                    "-",     "-",       "SVM,,>",     "UI,,",   EShLangFragmentMask | EShLangComputeMask },
    461         { "InterlockedOr",                    "-",     "-",       "SVM,",       "UI,",    EShLangFragmentMask | EShLangComputeMask },
    462         { "InterlockedXor",                   "-",     "-",       "SVM,,>",     "UI,,",   EShLangFragmentMask | EShLangComputeMask },
    463         { "InterlockedXor",                   "-",     "-",       "SVM,",       "UI,",    EShLangFragmentMask | EShLangComputeMask },
    464         { "isfinite",                         nullptr, "B" ,      "SVM",        "F",      EShLangAll },
    465         { "isinf",                            nullptr, "B" ,      "SVM",        "F",      EShLangAll },
    466         { "isnan",                            nullptr, "B" ,      "SVM",        "F",      EShLangAll },
    467         { "ldexp",                            nullptr, nullptr,   "SVM,",       "F,",     EShLangAll },
    468         { "length",                           "S",     "F",       "V",          "F",      EShLangAll },
    469         { "lerp",                             nullptr, nullptr,   "SVM,,",      "F,,",    EShLangAll },
    470         { "lit",                              "V4",    "F",       "S,,",        "F,,",    EShLangAll },
    471         { "log",                              nullptr, nullptr,   "SVM",        "F",      EShLangAll },
    472         { "log10",                            nullptr, nullptr,   "SVM",        "F",      EShLangAll },
    473         { "log2",                             nullptr, nullptr,   "SVM",        "F",      EShLangAll },
    474         { "mad",                              nullptr, nullptr,   "SVM,,",      "DFUI,,", EShLangAll },
    475         { "max",                              nullptr, nullptr,   "SVM,",       "FI,",    EShLangAll },
    476         { "min",                              nullptr, nullptr,   "SVM,",       "FI,",    EShLangAll },
    477         { "modf",                             nullptr, nullptr,   "SVM,>",      "FI,",    EShLangAll },
    478         { "msad4",                            "V4",    "U",       "S,V2,V4",    "U,,",    EShLangAll },
    479         { "mul",                              "S",     nullptr,   "S,S",        "FI,",    EShLangAll },
    480         { "mul",                              "V",     nullptr,   "S,V",        "FI,",    EShLangAll },
    481         { "mul",                              "M",     nullptr,   "S,M",        "FI,",    EShLangAll },
    482         { "mul",                              "V",     nullptr,   "V,S",        "FI,",    EShLangAll },
    483         { "mul",                              "S",     nullptr,   "V,V",        "FI,",    EShLangAll },
    484         { "mul",                              "#V",    nullptr,   "V,M",        "FI,",    EShLangAll },
    485         { "mul",                              "M",     nullptr,   "M,S",        "FI,",    EShLangAll },
    486         { "mul",                              "V",     nullptr,   "M,#V",       "FI,",    EShLangAll },
    487         // mat*mat form of mul is handled in createMatTimesMat()
    488         { "noise",                            "S",     "F",       "V",          "F",      EShLangFragmentMask },
    489         { "normalize",                        nullptr, nullptr,   "V",          "F",      EShLangAll },
    490         { "pow",                              nullptr, nullptr,   "SVM,",       "F,",     EShLangAll },
    491         // { "printf",                           "-",     "-",       "",        "",     EShLangAll }, TODO: varargs
    492         { "Process2DQuadTessFactorsAvg",      "-",     "-",       "V4,V2,>V4,>V2,>V2", "F,,,,", EShLangTessControlMask },
    493         { "Process2DQuadTessFactorsMax",      "-",     "-",       "V4,V2,>V4,>V2,>V2", "F,,,,", EShLangTessControlMask },
    494         { "Process2DQuadTessFactorsMin",      "-",     "-",       "V4,V2,>V4,>V2,>V2", "F,,,,", EShLangTessControlMask },
    495         { "ProcessIsolineTessFactors",        "-",     "-",       "S,,>,>",  "F,,,",   EShLangTessControlMask },
    496         { "ProcessQuadTessFactorsAvg",        "-",     "-",       "V4,S,>V4,>V2,>V2", "F,,,,",  EShLangTessControlMask },
    497         { "ProcessQuadTessFactorsMax",        "-",     "-",       "V4,S,>V4,>V2,>V2", "F,,,,",  EShLangTessControlMask },
    498         { "ProcessQuadTessFactorsMin",        "-",     "-",       "V4,S,>V4,>V2,>V2", "F,,,,",  EShLangTessControlMask },
    499         { "ProcessTriTessFactorsAvg",         "-",     "-",       "V3,S,>V3,>S,>S",   "F,,,,",  EShLangTessControlMask },
    500         { "ProcessTriTessFactorsMax",         "-",     "-",       "V3,S,>V3,>S,>S",   "F,,,,",  EShLangTessControlMask },
    501         { "ProcessTriTessFactorsMin",         "-",     "-",       "V3,S,>V3,>S,>S",   "F,,,,",  EShLangTessControlMask },
    502         { "radians",                          nullptr, nullptr,   "SVM",        "F",      EShLangAll },
    503         { "rcp",                              nullptr, nullptr,   "SVM",        "FD",     EShLangAll },
    504         { "reflect",                          nullptr, nullptr,   "V,",         "F,",     EShLangAll },
    505         { "refract",                          nullptr, nullptr,   "V,V,S",      "F,,",    EShLangAll },
    506         { "reversebits",                      nullptr, nullptr,   "SV",         "U",      EShLangAll },
    507         { "round",                            nullptr, nullptr,   "SVM",        "F",      EShLangAll },
    508         { "rsqrt",                            nullptr, nullptr,   "SVM",        "F",      EShLangAll },
    509         { "saturate",                         nullptr, nullptr ,  "SVM",        "F",      EShLangAll },
    510         { "sign",                             nullptr, nullptr,   "SVM",        "FI",     EShLangAll },
    511         { "sin",                              nullptr, nullptr,   "SVM",        "F",      EShLangAll },
    512         { "sincos",                           "-",     "-",       "SVM,>,>",    "F,,",    EShLangAll },
    513         { "sinh",                             nullptr, nullptr,   "SVM",        "F",      EShLangAll },
    514         { "smoothstep",                       nullptr, nullptr,   "SVM,,",      "F,,",    EShLangAll },
    515         { "sqrt",                             nullptr, nullptr,   "SVM",        "F",      EShLangAll },
    516         { "step",                             nullptr, nullptr,   "SVM,",       "F,",     EShLangAll },
    517         { "tan",                              nullptr, nullptr,   "SVM",        "F",      EShLangAll },
    518         { "tanh",                             nullptr, nullptr,   "SVM",        "F",      EShLangAll },
    519         { "tex1D",                            "V4",    "F",       "V1,S",       "S,F",    EShLangFragmentMask },
    520         { "tex1D",                            "V4",    "F",       "V1,S,V1,V1", "S,F,F,F",EShLangFragmentMask },
    521         { "tex1Dbias",                        "V4",    "F",       "V1,V4",      "S,F",    EShLangFragmentMask },
    522         { "tex1Dgrad",                        "V4",    "F",       "V1,V1,V1,V1","S,F,F,F",EShLangFragmentMask },
    523         { "tex1Dlod",                         "V4",    "F",       "V1,V4",      "S,F",    EShLangFragmentMask },
    524         { "tex1Dproj",                        "V4",    "F",       "V1,V4",      "S,F",    EShLangFragmentMask },
    525         { "tex2D",                            "V4",    "F",       "V2,V2",      "S,F",    EShLangFragmentMask },
    526         { "tex2D",                            "V4",    "F",       "V2,V2,V2,V2","S,F,F,F",EShLangFragmentMask },
    527         { "tex2Dbias",                        "V4",    "F",       "V2,V4",      "S,F",    EShLangFragmentMask },
    528         { "tex2Dgrad",                        "V4",    "F",       "V2,V2,V2,V2","S,F,F,F",EShLangFragmentMask },
    529         { "tex2Dlod",                         "V4",    "F",       "V2,V4",      "S,F",    EShLangFragmentMask },
    530         { "tex2Dproj",                        "V4",    "F",       "V2,V4",      "S,F",    EShLangFragmentMask },
    531         { "tex3D",                            "V4",    "F",       "V3,V3",      "S,F",    EShLangFragmentMask },
    532         { "tex3D",                            "V4",    "F",       "V3,V3,V3,V3","S,F,F,F",EShLangFragmentMask },
    533         { "tex3Dbias",                        "V4",    "F",       "V3,V4",      "S,F",    EShLangFragmentMask },
    534         { "tex3Dgrad",                        "V4",    "F",       "V3,V3,V3,V3","S,F,F,F",EShLangFragmentMask },
    535         { "tex3Dlod",                         "V4",    "F",       "V3,V4",      "S,F",    EShLangFragmentMask },
    536         { "tex3Dproj",                        "V4",    "F",       "V3,V4",      "S,F",    EShLangFragmentMask },
    537         { "texCUBE",                          "V4",    "F",       "V4,V3",      "S,F",    EShLangFragmentMask },
    538         { "texCUBE",                          "V4",    "F",       "V4,V3,V3,V3","S,F,F,F",EShLangFragmentMask },
    539         { "texCUBEbias",                      "V4",    "F",       "V4,V4",      "S,F",    EShLangFragmentMask },
    540         { "texCUBEgrad",                      "V4",    "F",       "V4,V3,V3,V3","S,F,F,F",EShLangFragmentMask },
    541         { "texCUBElod",                       "V4",    "F",       "V4,V4",      "S,F",    EShLangFragmentMask },
    542         { "texCUBEproj",                      "V4",    "F",       "V4,V4",      "S,F",    EShLangFragmentMask },
    543         { "transpose",                        "^M",    nullptr,   "M",          "F",      EShLangAll },
    544         { "trunc",                            nullptr, nullptr,   "SVM",        "F",      EShLangAll },
    545 
    546         // Texture object methods.  Return type can be overridden by shader declaration.
    547         // !O = no offset, O = offset, !A = no array, A = array
    548         { "Sample",             /*!O !A*/     "V4",    nullptr,   "%V,S,V",     "FIU,S,F",     EShLangFragmentMask },
    549         { "Sample",             /* O !A*/     "V4",    nullptr,   "%V,S,V,V",   "FIU,S,F,I",   EShLangFragmentMask },
    550         { "Sample",             /*!O  A*/     "V4",    nullptr,   "@V,S,V",     "FIU,S,F",     EShLangFragmentMask },
    551         { "Sample",             /* O  A*/     "V4",    nullptr,   "@V,S,V,V",   "FIU,S,F,I",   EShLangFragmentMask },
    552 
    553         { "SampleBias",         /*!O !A*/     "V4",    nullptr,   "%V,S,V,S",   "FIU,S,F,F",   EShLangFragmentMask },
    554         { "SampleBias",         /* O !A*/     "V4",    nullptr,   "%V,S,V,S,V", "FIU,S,F,F,I", EShLangFragmentMask },
    555         { "SampleBias",         /*!O  A*/     "V4",    nullptr,   "@V,S,V,S",   "FIU,S,F,F",   EShLangFragmentMask },
    556         { "SampleBias",         /* O  A*/     "V4",    nullptr,   "@V,S,V,S,V", "FIU,S,F,F,I", EShLangFragmentMask },
    557 
    558         // { "SampleCmp",          /*!O !A*/     "V4",    nullptr,   "%V,S,V,S",   "FIU,S,F,F",   EShLangFragmentMask },
    559         // { "SampleCmp",          /* O !A*/     "V4",    nullptr,   "%V,S,V,S,V", "FIU,S,F,F,I", EShLangFragmentMask },
    560         // { "SampleCmp",          /*!O  A*/     "V4",    nullptr,   "@V,S,V,S",   "FIU,S,F,F",   EShLangFragmentMask },
    561         // { "SampleCmp",          /* O  A*/     "V4",    nullptr,   "@V,S,V,S,V", "FIU,S,F,F,I", EShLangFragmentMask },
    562 
    563         // { "SampleCmpLevelZero", /*!O !A*/     "V4",    nullptr,   "%V,S,V",     "FIU,S,F",     EShLangFragmentMask },
    564         // { "SampleCmpLevelZero", /* O !A*/     "V4",    nullptr,   "%V,S,V,V",   "FIU,S,F,I",   EShLangFragmentMask },
    565         // { "SampleCmpLevelZero", /*!O  A*/     "V4",    nullptr,   "@V,S,V",     "FIU,S,F",     EShLangFragmentMask },
    566         // { "SampleCmpLevelZero", /* O  A*/     "V4",    nullptr,   "@V,S,V,V",   "FIU,S,F,I",   EShLangFragmentMask },
    567 
    568         { "SampleGrad",         /*!O !A*/     "V4",    nullptr,   "%V,S,V,V,V",   "FIU,S,F,F,F",   EShLangAll },
    569         { "SampleGrad",         /* O !A*/     "V4",    nullptr,   "%V,S,V,V,V,V", "FIU,S,F,F,F,I", EShLangAll },
    570         { "SampleGrad",         /*!O  A*/     "V4",    nullptr,   "@V,S,V,V,V",   "FIU,S,F,F,F",   EShLangAll },
    571         { "SampleGrad",         /* O  A*/     "V4",    nullptr,   "@V,S,V,V,V,V", "FIU,S,F,F,F,I", EShLangAll },
    572 
    573         // { "SampleLevel",        /*!O !A*/     "V4",    nullptr,   "%V,S,V,S",   "FIU,S,F,F",       EShLangFragmentMask },
    574         // { "SampleLevel",        /* O !A*/     "V4",    nullptr,   "%V,S,V,S,V", "FIU,S,F,F,I",     EShLangFragmentMask },
    575         // { "SampleLevel",        /*!O  A*/     "V4",    nullptr,   "@V,S,V,S",   "FIU,S,F,F",       EShLangFragmentMask },
    576         // { "SampleLevel",        /* O  A*/     "V4",    nullptr,   "@V,S,V,S,V", "FIU,S,F,F,I",     EShLangFragmentMask },
    577 
    578         // TODO: ...
    579         // { "Load",                            "V4",    nullptr,   "%V,V",       "FIU,I",           EShLangFragmentMask },
    580         // { "Load", /* +sampleidex*/           "V4",    nullptr,   "%V,V,S",     "FIU,I,I",         EShLangFragmentMask },
    581         // { "Load", /* +samplindex, offset*/   "V4",    nullptr,   "%V,V,S,V",   "FIU,I,I,I",       EShLangFragmentMask },
    582         // { "Load",                            "V4",    nullptr,   "@V,V",       "FIU,I",           EShLangFragmentMask },
    583         // { "Load", /* +sampleidex*/           "V4",    nullptr,   "@V,V,S",     "FIU,I,I",         EShLangFragmentMask },
    584         // { "Load", /* +samplindex, offset*/   "V4",    nullptr,   "@V,V,S,V",   "FIU,I,I,I",       EShLangFragmentMask },
    585 
    586         // table of overloads from: https://msdn.microsoft.com/en-us/library/windows/desktop/bb509693(v=vs.85).aspx
    587         //
    588         // UINT Width
    589         // UINT MipLevel, UINT Width, UINT NumberOfLevels
    590         { "GetDimensions",   /* 1D */         "-",     "-",       "%V1,>S",             "FUI,U",         EShLangAll },
    591         { "GetDimensions",   /* 1D */         "-",     "-",       "%V1,>S",             "FUI,F",         EShLangAll },
    592         { "GetDimensions",   /* 1D */         "-",     "-",       "%V1,S,>S,>S",        "FUI,U,U,U",     EShLangAll },
    593         { "GetDimensions",   /* 1D */         "-",     "-",       "%V1,S,>S,>S",        "FUI,U,F,F",     EShLangAll },
    594 
    595         // UINT Width, UINT Elements
    596         // UINT MipLevel, UINT Width, UINT Elements, UINT NumberOfLevels
    597         { "GetDimensions",   /* 1DArray */    "-",     "-",       "@V1,>S,>S",          "FUI,U,U",       EShLangAll },
    598         { "GetDimensions",   /* 1DArray */    "-",     "-",       "@V1,>S,>S",          "FUI,F,F",       EShLangAll },
    599         { "GetDimensions",   /* 1DArray */    "-",     "-",       "@V1,S,>S,>S,>S",     "FUI,U,U,U,U",   EShLangAll },
    600         { "GetDimensions",   /* 1DArray */    "-",     "-",       "@V1,S,>S,>S,>S",     "FUI,U,F,F,F",   EShLangAll },
    601 
    602         // UINT Width, UINT Height
    603         // UINT MipLevel, UINT Width, UINT Height, UINT NumberOfLevels
    604         { "GetDimensions",   /* 2D */         "-",     "-",       "%V2,>S,>S",          "FUI,U,U",       EShLangAll },
    605         { "GetDimensions",   /* 2D */         "-",     "-",       "%V2,>S,>S",          "FUI,F,F",       EShLangAll },
    606         { "GetDimensions",   /* 2D */         "-",     "-",       "%V2,S,>S,>S,>S",     "FUI,U,U,U,U",   EShLangAll },
    607         { "GetDimensions",   /* 2D */         "-",     "-",       "%V2,S,>S,>S,>S",     "FUI,U,F,F,F",   EShLangAll },
    608 
    609         // UINT Width, UINT Height, UINT Elements
    610         // UINT MipLevel, UINT Width, UINT Height, UINT Elements, UINT NumberOfLevels
    611         { "GetDimensions",   /* 2DArray */    "-",     "-",       "@V2,>S,>S,>S",       "FUI,U,U,U",     EShLangAll },
    612         { "GetDimensions",   /* 2DArray */    "-",     "-",       "@V2,>S,>S,>S",       "FUI,F,F,F",     EShLangAll },
    613         { "GetDimensions",   /* 2DArray */    "-",     "-",       "@V2,S,>S,>S,>S,>S",  "FUI,U,U,U,U,U", EShLangAll },
    614         { "GetDimensions",   /* 2DArray */    "-",     "-",       "@V2,S,>S,>S,>S,>S",  "FUI,U,F,F,F,F", EShLangAll },
    615 
    616         // UINT Width, UINT Height, UINT Depth
    617         // UINT MipLevel, UINT Width, UINT Height, UINT Depth, UINT NumberOfLevels
    618         { "GetDimensions",   /* 3D */         "-",     "-",       "%V3,>S,>S,>S",       "FUI,U,U,U",     EShLangAll },
    619         { "GetDimensions",   /* 3D */         "-",     "-",       "%V3,>S,>S,>S",       "FUI,F,F,F",     EShLangAll },
    620         { "GetDimensions",   /* 3D */         "-",     "-",       "%V3,S,>S,>S,>S,>S",  "FUI,U,U,U,U,U", EShLangAll },
    621         { "GetDimensions",   /* 3D */         "-",     "-",       "%V3,S,>S,>S,>S,>S",  "FUI,U,F,F,F,F", EShLangAll },
    622 
    623         // UINT Width, UINT Height
    624         // UINT MipLevel, UINT Width, UINT Height, UINT NumberOfLevels
    625         { "GetDimensions",   /* Cube */       "-",     "-",       "%V4,>S,>S",          "FUI,U,U",       EShLangAll },
    626         { "GetDimensions",   /* Cube */       "-",     "-",       "%V4,>S,>S",          "FUI,F,F",       EShLangAll },
    627         { "GetDimensions",   /* Cube */       "-",     "-",       "%V4,S,>S,>S,>S",     "FUI,U,U,U,U",   EShLangAll },
    628         { "GetDimensions",   /* Cube */       "-",     "-",       "%V4,S,>S,>S,>S",     "FUI,U,F,F,F",   EShLangAll },
    629 
    630         // UINT Width, UINT Height, UINT Elements
    631         // UINT MipLevel, UINT Width, UINT Height, UINT Elements, UINT NumberOfLevels
    632         { "GetDimensions",   /* CubeArray */  "-",     "-",       "@V4,>S,>S,>S",       "FUI,U,U,U",     EShLangAll },
    633         { "GetDimensions",   /* CubeArray */  "-",     "-",       "@V4,>S,>S,>S",       "FUI,F,F,F",     EShLangAll },
    634         { "GetDimensions",   /* CubeArray */  "-",     "-",       "@V4,S,>S,>S,>S,>S",  "FUI,U,U,U,U,U", EShLangAll },
    635         { "GetDimensions",   /* CubeArray */  "-",     "-",       "@V4,S,>S,>S,>S,>S",  "FUI,U,F,F,F,F", EShLangAll },
    636 
    637         // TODO: GetDimensions for Texture2DMS, Texture2DMSArray
    638         // UINT Width, UINT Height, UINT Samples
    639         // UINT Width, UINT Height, UINT Elements, UINT Samples
    640 
    641         // Mark end of list, since we want to avoid a range-based for, as some compilers don't handle it yet.
    642         { nullptr,                            nullptr, nullptr,   nullptr,      nullptr,  0 },
    643     };
    644 
    645     // Set this to true to avoid generating prototypes that will be invalid for the GLSL parser.
    646     // TODO: turn it off (and remove the code) when the HLSL parser can be used to parse builtins.
    647     static const bool skipInvalidGlsl = true;
    648 
    649     // Create prototypes for the intrinsics.  TODO: Avoid ranged based for until all compilers can handle it.
    650     for (int icount = 0; hlslIntrinsics[icount].name; ++icount) {
    651         const auto& intrinsic = hlslIntrinsics[icount];
    652 
    653         for (int stage = 0; stage < EShLangCount; ++stage) {                                // for each stage...
    654             if ((intrinsic.stage & (1<<stage)) == 0) // skip inapplicable stages
    655                 continue;
    656 
    657             // reference to either the common builtins, or stage specific builtins.
    658             TString& s = (intrinsic.stage == EShLangAll) ? commonBuiltins : stageBuiltins[stage];
    659 
    660             for (const char* argOrder = intrinsic.argOrder; !IsEndOfArg(argOrder); ++argOrder) { // for each order...
    661                 const bool isTexture   = IsTextureType(*argOrder);
    662                 const bool isArrayed   = IsTextureArrayed(*argOrder);
    663                 const int fixedVecSize = FixedVecSize(argOrder);
    664 
    665                 // calculate min and max vector and matrix dimensions
    666                 int dim0Min = 1;
    667                 int dim0Max = 1;
    668                 int dim1Min = 1;
    669                 int dim1Max = 1;
    670 
    671                 FindVectorMatrixBounds(argOrder, fixedVecSize, dim0Min, dim0Max, dim1Min, dim1Max);
    672 
    673                 for (const char* argType = intrinsic.argType; !IsEndOfArg(argType); ++argType) { // for each type...
    674                     for (int dim0 = dim0Min; dim0 <= dim0Max; ++dim0) {          // for each dim 0...
    675                         for (int dim1 = dim1Min; dim1 <= dim1Max; ++dim1) {      // for each dim 1...
    676                             const char* retOrder = intrinsic.retOrder ? intrinsic.retOrder : argOrder;
    677                             const char* retType  = intrinsic.retType  ? intrinsic.retType  : argType;
    678 
    679                             if (skipInvalidGlsl && !IsValidGlsl(intrinsic.name, *retOrder, *retType, *argOrder, *argType,
    680                                                                 dim0, dim1, dim0Max, dim1Max))
    681                                 continue;
    682 
    683                             // Reject some forms of sample methods that don't exist.
    684                             if (isTexture && IsIllegalSample(intrinsic.name, argOrder, dim0))
    685                                 continue;
    686 
    687                             AppendTypeName(s, retOrder, retType, dim0, dim1);  // add return type
    688                             s.append(" ");                                     // space between type and name
    689                             s.append(intrinsic.name);                          // intrinsic name
    690                             s.append("(");                                     // open paren
    691 
    692                             // Append argument types, if any.
    693                             for (int arg = 0; ; ++arg) {
    694                                 const char* nthArgOrder(NthArg(argOrder, arg));
    695                                 const char* nthArgType(NthArg(argType, arg));
    696 
    697                                 if (nthArgOrder == nullptr || nthArgType == nullptr)
    698                                     break;
    699 
    700                                 // cube textures use vec3 coordinates
    701                                 int argDim0 = isTexture && arg > 0 ? std::min(dim0, 3) : dim0;
    702 
    703                                 // arrayed textures have one extra coordinate dimension
    704                                 if (isArrayed && arg == 2)
    705                                     argDim0++;
    706 
    707                                 // For textures, the 1D case isn't a 1-vector, but a scalar.
    708                                 if (isTexture && argDim0 == 1 && arg > 0 && *nthArgOrder == 'V')
    709                                     nthArgOrder = "S";
    710 
    711                                 s.append(arg > 0 ? ", ": "");  // comma separator if needed
    712 
    713                                 if (*nthArgOrder == '>') {           // output params
    714                                     ++nthArgOrder;
    715                                     s.append("out ");
    716                                 } else if (*nthArgOrder == '<') {    // input params
    717                                     ++nthArgOrder;
    718                                     s.append("in ");
    719                                 }
    720 
    721                                 // Comma means use the 1st argument order and type.
    722                                 if (*nthArgOrder == ',' || *nthArgOrder == '\0') nthArgOrder = argOrder;
    723                                 if (*nthArgType == ',' || *nthArgType == '\0') nthArgType = argType;
    724 
    725                                 AppendTypeName(s, nthArgOrder, nthArgType, argDim0, dim1); // Add arguments
    726                             }
    727 
    728                             s.append(");\n");            // close paren and trailing semicolon
    729                         }
    730                     }
    731                 }
    732 
    733                 // skip over special characters
    734                 if (isTexture)
    735                     ++argOrder;
    736                 if (isdigit(argOrder[1]))
    737                     ++argOrder;
    738             }
    739 
    740             if (intrinsic.stage == EShLangAll) // common builtins are only added once.
    741                 break;
    742         }
    743     }
    744 
    745     createMatTimesMat(); // handle this case separately, for convenience
    746 
    747     // printf("Common:\n%s\n",   getCommonString().c_str());
    748     // printf("Frag:\n%s\n",     getStageString(EShLangFragment).c_str());
    749     // printf("Vertex:\n%s\n",   getStageString(EShLangVertex).c_str());
    750     // printf("Geo:\n%s\n",      getStageString(EShLangGeometry).c_str());
    751     // printf("TessCtrl:\n%s\n", getStageString(EShLangTessControl).c_str());
    752     // printf("TessEval:\n%s\n", getStageString(EShLangTessEvaluation).c_str());
    753     // printf("Compute:\n%s\n",  getStageString(EShLangCompute).c_str());
    754 }
    755 
    756 //
    757 // Add context-dependent built-in functions and variables that are present
    758 // for the given version and profile.  All the results are put into just the
    759 // commonBuiltins, because it is called for just a specific stage.  So,
    760 // add stage-specific entries to the commonBuiltins, and only if that stage
    761 // was requested.
    762 //
    763 void TBuiltInParseablesHlsl::initialize(const TBuiltInResource& /*resources*/, int /*version*/, EProfile /*profile*/,
    764                                         const SpvVersion& /*spvVersion*/, EShLanguage /*language*/)
    765 {
    766 }
    767 
    768 
    769 //
    770 // Finish adding/processing context-independent built-in symbols.
    771 // 1) Programmatically add symbols that could not be added by simple text strings above.
    772 // 2) Map built-in functions to operators, for those that will turn into an operation node
    773 //    instead of remaining a function call.
    774 // 3) Tag extension-related symbols added to their base version with their extensions, so
    775 //    that if an early version has the extension turned off, there is an error reported on use.
    776 //
    777 void TBuiltInParseablesHlsl::identifyBuiltIns(int /*version*/, EProfile /*profile*/, const SpvVersion& /*spvVersion*/, EShLanguage /*language*/,
    778                                               TSymbolTable& symbolTable)
    779 {
    780     // symbolTable.relateToOperator("abort",                       EOpAbort);
    781     symbolTable.relateToOperator("abs",                         EOpAbs);
    782     symbolTable.relateToOperator("acos",                        EOpAcos);
    783     symbolTable.relateToOperator("all",                         EOpAll);
    784     symbolTable.relateToOperator("AllMemoryBarrier",            EOpMemoryBarrier);
    785     symbolTable.relateToOperator("AllMemoryBarrierWithGroupSync", EOpAllMemoryBarrierWithGroupSync);
    786     symbolTable.relateToOperator("any",                         EOpAny);
    787     symbolTable.relateToOperator("asdouble",                    EOpAsDouble);
    788     symbolTable.relateToOperator("asfloat",                     EOpIntBitsToFloat);
    789     symbolTable.relateToOperator("asin",                        EOpAsin);
    790     symbolTable.relateToOperator("asint",                       EOpFloatBitsToInt);
    791     symbolTable.relateToOperator("asuint",                      EOpFloatBitsToUint);
    792     symbolTable.relateToOperator("atan",                        EOpAtan);
    793     symbolTable.relateToOperator("atan2",                       EOpAtan);
    794     symbolTable.relateToOperator("ceil",                        EOpCeil);
    795     // symbolTable.relateToOperator("CheckAccessFullyMapped");
    796     symbolTable.relateToOperator("clamp",                       EOpClamp);
    797     symbolTable.relateToOperator("clip",                        EOpClip);
    798     symbolTable.relateToOperator("cos",                         EOpCos);
    799     symbolTable.relateToOperator("cosh",                        EOpCosh);
    800     symbolTable.relateToOperator("countbits",                   EOpBitCount);
    801     symbolTable.relateToOperator("cross",                       EOpCross);
    802     // symbolTable.relateToOperator("D3DCOLORtoUBYTE4",            EOpD3DCOLORtoUBYTE4);
    803     symbolTable.relateToOperator("ddx",                         EOpDPdx);
    804     symbolTable.relateToOperator("ddx_coarse",                  EOpDPdxCoarse);
    805     symbolTable.relateToOperator("ddx_fine",                    EOpDPdxFine);
    806     symbolTable.relateToOperator("ddy",                         EOpDPdy);
    807     symbolTable.relateToOperator("ddy_coarse",                  EOpDPdyCoarse);
    808     symbolTable.relateToOperator("ddy_fine",                    EOpDPdyFine);
    809     symbolTable.relateToOperator("degrees",                     EOpDegrees);
    810     symbolTable.relateToOperator("determinant",                 EOpDeterminant);
    811     symbolTable.relateToOperator("DeviceMemoryBarrier",         EOpGroupMemoryBarrier);
    812     symbolTable.relateToOperator("DeviceMemoryBarrierWithGroupSync", EOpGroupMemoryBarrierWithGroupSync); // ...
    813     symbolTable.relateToOperator("distance",                    EOpDistance);
    814     symbolTable.relateToOperator("dot",                         EOpDot);
    815     symbolTable.relateToOperator("dst",                         EOpDst);
    816     // symbolTable.relateToOperator("errorf",                      EOpErrorf);
    817     symbolTable.relateToOperator("EvaluateAttributeAtCentroid", EOpInterpolateAtCentroid);
    818     symbolTable.relateToOperator("EvaluateAttributeAtSample",   EOpInterpolateAtSample);
    819     symbolTable.relateToOperator("EvaluateAttributeSnapped",    EOpEvaluateAttributeSnapped);
    820     symbolTable.relateToOperator("exp",                         EOpExp);
    821     symbolTable.relateToOperator("exp2",                        EOpExp2);
    822     symbolTable.relateToOperator("f16tof32",                    EOpF16tof32);
    823     symbolTable.relateToOperator("f32tof16",                    EOpF32tof16);
    824     symbolTable.relateToOperator("faceforward",                 EOpFaceForward);
    825     symbolTable.relateToOperator("firstbithigh",                EOpFindMSB);
    826     symbolTable.relateToOperator("firstbitlow",                 EOpFindLSB);
    827     symbolTable.relateToOperator("floor",                       EOpFloor);
    828     symbolTable.relateToOperator("fma",                         EOpFma);
    829     symbolTable.relateToOperator("fmod",                        EOpMod);
    830     symbolTable.relateToOperator("frac",                        EOpFract);
    831     symbolTable.relateToOperator("frexp",                       EOpFrexp);
    832     symbolTable.relateToOperator("fwidth",                      EOpFwidth);
    833     // symbolTable.relateToOperator("GetRenderTargetSampleCount");
    834     // symbolTable.relateToOperator("GetRenderTargetSamplePosition");
    835     symbolTable.relateToOperator("GroupMemoryBarrier",          EOpWorkgroupMemoryBarrier);
    836     symbolTable.relateToOperator("GroupMemoryBarrierWithGroupSync", EOpWorkgroupMemoryBarrierWithGroupSync);
    837     symbolTable.relateToOperator("InterlockedAdd",              EOpInterlockedAdd);
    838     symbolTable.relateToOperator("InterlockedAnd",              EOpInterlockedAnd);
    839     symbolTable.relateToOperator("InterlockedCompareExchange",  EOpInterlockedCompareExchange);
    840     symbolTable.relateToOperator("InterlockedCompareStore",     EOpInterlockedCompareStore);
    841     symbolTable.relateToOperator("InterlockedExchange",         EOpInterlockedExchange);
    842     symbolTable.relateToOperator("InterlockedMax",              EOpInterlockedMax);
    843     symbolTable.relateToOperator("InterlockedMin",              EOpInterlockedMin);
    844     symbolTable.relateToOperator("InterlockedOr",               EOpInterlockedOr);
    845     symbolTable.relateToOperator("InterlockedXor",              EOpInterlockedXor);
    846     symbolTable.relateToOperator("isfinite",                    EOpIsFinite);
    847     symbolTable.relateToOperator("isinf",                       EOpIsInf);
    848     symbolTable.relateToOperator("isnan",                       EOpIsNan);
    849     symbolTable.relateToOperator("ldexp",                       EOpLdexp);
    850     symbolTable.relateToOperator("length",                      EOpLength);
    851     symbolTable.relateToOperator("lerp",                        EOpMix);
    852     symbolTable.relateToOperator("lit",                         EOpLit);
    853     symbolTable.relateToOperator("log",                         EOpLog);
    854     symbolTable.relateToOperator("log10",                       EOpLog10);
    855     symbolTable.relateToOperator("log2",                        EOpLog2);
    856     symbolTable.relateToOperator("mad",                         EOpFma);
    857     symbolTable.relateToOperator("max",                         EOpMax);
    858     symbolTable.relateToOperator("min",                         EOpMin);
    859     symbolTable.relateToOperator("modf",                        EOpModf);
    860     // symbolTable.relateToOperator("msad4",                       EOpMsad4);
    861     symbolTable.relateToOperator("mul",                         EOpGenMul);
    862     // symbolTable.relateToOperator("noise",                    EOpNoise); // TODO: check return type
    863     symbolTable.relateToOperator("normalize",                   EOpNormalize);
    864     symbolTable.relateToOperator("pow",                         EOpPow);
    865     // symbolTable.relateToOperator("printf",                     EOpPrintf);
    866     // symbolTable.relateToOperator("Process2DQuadTessFactorsAvg");
    867     // symbolTable.relateToOperator("Process2DQuadTessFactorsMax");
    868     // symbolTable.relateToOperator("Process2DQuadTessFactorsMin");
    869     // symbolTable.relateToOperator("ProcessIsolineTessFactors");
    870     // symbolTable.relateToOperator("ProcessQuadTessFactorsAvg");
    871     // symbolTable.relateToOperator("ProcessQuadTessFactorsMax");
    872     // symbolTable.relateToOperator("ProcessQuadTessFactorsMin");
    873     // symbolTable.relateToOperator("ProcessTriTessFactorsAvg");
    874     // symbolTable.relateToOperator("ProcessTriTessFactorsMax");
    875     // symbolTable.relateToOperator("ProcessTriTessFactorsMin");
    876     symbolTable.relateToOperator("radians",                     EOpRadians);
    877     symbolTable.relateToOperator("rcp",                         EOpRcp);
    878     symbolTable.relateToOperator("reflect",                     EOpReflect);
    879     symbolTable.relateToOperator("refract",                     EOpRefract);
    880     symbolTable.relateToOperator("reversebits",                 EOpBitFieldReverse);
    881     symbolTable.relateToOperator("round",                       EOpRoundEven);
    882     symbolTable.relateToOperator("rsqrt",                       EOpInverseSqrt);
    883     symbolTable.relateToOperator("saturate",                    EOpSaturate);
    884     symbolTable.relateToOperator("sign",                        EOpSign);
    885     symbolTable.relateToOperator("sin",                         EOpSin);
    886     symbolTable.relateToOperator("sincos",                      EOpSinCos);
    887     symbolTable.relateToOperator("sinh",                        EOpSinh);
    888     symbolTable.relateToOperator("smoothstep",                  EOpSmoothStep);
    889     symbolTable.relateToOperator("sqrt",                        EOpSqrt);
    890     symbolTable.relateToOperator("step",                        EOpStep);
    891     symbolTable.relateToOperator("tan",                         EOpTan);
    892     symbolTable.relateToOperator("tanh",                        EOpTanh);
    893     symbolTable.relateToOperator("tex1D",                       EOpTexture);
    894     symbolTable.relateToOperator("tex1Dbias",                   EOpTextureBias);
    895     symbolTable.relateToOperator("tex1Dgrad",                   EOpTextureGrad);
    896     symbolTable.relateToOperator("tex1Dlod",                    EOpTextureLod);
    897     symbolTable.relateToOperator("tex1Dproj",                   EOpTextureProj);
    898     symbolTable.relateToOperator("tex2D",                       EOpTexture);
    899     symbolTable.relateToOperator("tex2Dbias",                   EOpTextureBias);
    900     symbolTable.relateToOperator("tex2Dgrad",                   EOpTextureGrad);
    901     symbolTable.relateToOperator("tex2Dlod",                    EOpTextureLod);
    902     symbolTable.relateToOperator("tex2Dproj",                   EOpTextureProj);
    903     symbolTable.relateToOperator("tex3D",                       EOpTexture);
    904     symbolTable.relateToOperator("tex3Dbias",                   EOpTextureBias);
    905     symbolTable.relateToOperator("tex3Dgrad",                   EOpTextureGrad);
    906     symbolTable.relateToOperator("tex3Dlod",                    EOpTextureLod);
    907     symbolTable.relateToOperator("tex3Dproj",                   EOpTextureProj);
    908     symbolTable.relateToOperator("texCUBE",                     EOpTexture);
    909     symbolTable.relateToOperator("texCUBEbias",                 EOpTextureBias);
    910     symbolTable.relateToOperator("texCUBEgrad",                 EOpTextureGrad);
    911     symbolTable.relateToOperator("texCUBElod",                  EOpTextureLod);
    912     symbolTable.relateToOperator("texCUBEproj",                 EOpTextureProj);
    913     symbolTable.relateToOperator("transpose",                   EOpTranspose);
    914     symbolTable.relateToOperator("trunc",                       EOpTrunc);
    915 
    916     // Texture methods
    917     symbolTable.relateToOperator("Sample",                      EOpMethodSample);
    918     symbolTable.relateToOperator("SampleBias",                  EOpMethodSampleBias);
    919     // symbolTable.relateToOperator("SampleCmp",                   EOpMethodSampleCmp);
    920     // symbolTable.relateToOperator("SampleCmpLevelZero",          EOpMethodSampleCmpLevelZero);
    921     symbolTable.relateToOperator("SampleGrad",                  EOpMethodSampleGrad);
    922     // symbolTable.relateToOperator("SampleLevel",                 EOpMethodSampleLevel);
    923     // symbolTable.relateToOperator("Load",                        EOpMethodLoad);
    924     symbolTable.relateToOperator("GetDimensions",               EOpMethodGetDimensions);
    925 }
    926 
    927 //
    928 // Add context-dependent (resource-specific) built-ins not handled by the above.  These
    929 // would be ones that need to be programmatically added because they cannot
    930 // be added by simple text strings.  For these, also
    931 // 1) Map built-in functions to operators, for those that will turn into an operation node
    932 //    instead of remaining a function call.
    933 // 2) Tag extension-related symbols added to their base version with their extensions, so
    934 //    that if an early version has the extension turned off, there is an error reported on use.
    935 //
    936 void TBuiltInParseablesHlsl::identifyBuiltIns(int /*version*/, EProfile /*profile*/, const SpvVersion& /*spvVersion*/, EShLanguage /*language*/,
    937                                               TSymbolTable& /*symbolTable*/, const TBuiltInResource& /*resources*/)
    938 {
    939 }
    940 
    941 
    942 } // end namespace glslang
    943