Home | History | Annotate | Download | only in MachineIndependent
      1 //
      2 //Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
      3 //Copyright (C) 2012-2013 LunarG, Inc.
      4 //
      5 //All rights reserved.
      6 //
      7 //Redistribution and use in source and binary forms, with or without
      8 //modification, are permitted provided that the following conditions
      9 //are met:
     10 //
     11 //    Redistributions of source code must retain the above copyright
     12 //    notice, this list of conditions and the following disclaimer.
     13 //
     14 //    Redistributions in binary form must reproduce the above
     15 //    copyright notice, this list of conditions and the following
     16 //    disclaimer in the documentation and/or other materials provided
     17 //    with the distribution.
     18 //
     19 //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
     20 //    contributors may be used to endorse or promote products derived
     21 //    from this software without specific prior written permission.
     22 //
     23 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     24 //"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     25 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     26 //FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     27 //COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     28 //INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     29 //BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     30 //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     31 //CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32 //LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     33 //ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     34 //POSSIBILITY OF SUCH DAMAGE.
     35 //
     36 
     37 //
     38 // Help manage multiple profiles, versions, extensions etc.
     39 //
     40 // These don't return error codes, as the presumption is parsing will
     41 // always continue as if the tested feature were enabled, and thus there
     42 // is no error recovery needed.
     43 //
     44 
     45 //
     46 // HOW TO add a feature enabled by an extension.
     47 //
     48 // To add a new hypothetical "Feature F" to the front end, where an extension
     49 // "XXX_extension_X" can be used to enable the feature, do the following.
     50 //
     51 // OVERVIEW: Specific features are what are error-checked for, not
     52 //    extensions:  A specific Feature F might be enabled by an extension, or a
     53 //    particular version in a particular profile, or a stage, or combinations, etc.
     54 //
     55 //    The basic mechanism is to use the following to "declare" all the things that
     56 //    enable/disable Feature F, in a code path that implements Feature F:
     57 //
     58 //        requireProfile()
     59 //        profileRequires()
     60 //        requireStage()
     61 //        checkDeprecated()
     62 //        requireNotRemoved()
     63 //        requireExtensions()
     64 //
     65 //    Typically, only the first two calls are needed.  They go into a code path that
     66 //    implements Feature F, and will log the proper error/warning messages.  Parsing
     67 //    will then always continue as if the tested feature was enabled.
     68 //
     69 //    There is typically no if-testing or conditional parsing, just insertion of the calls above.
     70 //    However, if symbols specific to the extension are added (step 5), they will
     71 //    only be added under tests that the minimum version and profile are present.
     72 //
     73 // 1) Add a symbol name for the extension string at the bottom of Versions.h:
     74 //
     75 //     const char* const XXX_extension_X = "XXX_extension_X";
     76 //
     77 // 2) Add extension initialization to TParseVersions::initializeExtensionBehavior(),
     78 //    the first function below:
     79 //
     80 //     extensionBehavior[XXX_extension_X] = EBhDisable;
     81 //
     82 // 3) Add any preprocessor directives etc. in the next function, TParseVersions::getPreamble():
     83 //
     84 //           "#define XXX_extension_X 1\n"
     85 //
     86 //    The new-line is important, as that ends preprocess tokens.
     87 //
     88 // 4) Insert a profile check in the feature's path (unless all profiles support the feature,
     89 //    for some version level).  That is, call requireProfile() to constrain the profiles, e.g.:
     90 //
     91 //         // ... in a path specific to Feature F...
     92 //         requireProfile(loc,
     93 //                        ECoreProfile | ECompatibilityProfile,
     94 //                        "Feature F");
     95 //
     96 // 5) For each profile that supports the feature, insert version/extension checks:
     97 //
     98 //    The mostly likely scenario is that Feature F can only be used with a
     99 //    particular profile if XXX_extension_X is present or the version is
    100 //    high enough that the core specification already incorporated it.
    101 //
    102 //        // following the requireProfile() call...
    103 //        profileRequires(loc,
    104 //                        ECoreProfile | ECompatibilityProfile,
    105 //                        420,             // 0 if no version incorporated the feature into the core spec.
    106 //                        XXX_extension_X, // can be a list of extensions that all add the feature
    107 //                        "Feature F Description");
    108 //
    109 //    This allows the feature if either A) one of the extensions is enabled or
    110 //    B) the version is high enough.  If no version yet incorporates the feature
    111 //    into core, pass in 0.
    112 //
    113 //    This can be called multiple times, if different profiles support the
    114 //    feature starting at different version numbers or with different
    115 //    extensions.
    116 //
    117 //    This must be called for each profile allowed by the initial call to requireProfile().
    118 //
    119 //    Profiles are all masks, which can be "or"-ed together.
    120 //
    121 //        ENoProfile
    122 //        ECoreProfile
    123 //        ECompatibilityProfile
    124 //        EEsProfile
    125 //
    126 //    The ENoProfile profile is only for desktop, before profiles showed up in version 150;
    127 //    All other #version with no profile default to either es or core, and so have profiles.
    128 //
    129 //    You can select all but a particular profile using ~.  The following basically means "desktop":
    130 //
    131 //        ~EEsProfile
    132 //
    133 // 6) If built-in symbols are added by the extension, add them in Initialize.cpp:  Their use
    134 //    will be automatically error checked against the extensions enabled at that moment.
    135 //    see the comment at the top of Initialize.cpp for where to put them.  Establish them at
    136 //    the earliest release that supports the extension.  Then, tag them with the
    137 //    set of extensions that both enable them and are necessary, given the version of the symbol
    138 //    table. (There is a different symbol table for each version.)
    139 //
    140 
    141 #include "parseVersions.h"
    142 #include "localintermediate.h"
    143 
    144 namespace glslang {
    145 
    146 //
    147 // Initialize all extensions, almost always to 'disable', as once their features
    148 // are incorporated into a core version, their features are supported through allowing that
    149 // core version, not through a pseudo-enablement of the extension.
    150 //
    151 void TParseVersions::initializeExtensionBehavior()
    152 {
    153     extensionBehavior[E_GL_OES_texture_3D]                   = EBhDisable;
    154     extensionBehavior[E_GL_OES_standard_derivatives]         = EBhDisable;
    155     extensionBehavior[E_GL_EXT_frag_depth]                   = EBhDisable;
    156     extensionBehavior[E_GL_OES_EGL_image_external]           = EBhDisable;
    157     extensionBehavior[E_GL_EXT_shader_texture_lod]           = EBhDisable;
    158 
    159     extensionBehavior[E_GL_ARB_texture_rectangle]            = EBhDisable;
    160     extensionBehavior[E_GL_3DL_array_objects]                = EBhDisable;
    161     extensionBehavior[E_GL_ARB_shading_language_420pack]     = EBhDisable;
    162     extensionBehavior[E_GL_ARB_texture_gather]               = EBhDisable;
    163     extensionBehavior[E_GL_ARB_gpu_shader5]                  = EBhDisablePartial;
    164     extensionBehavior[E_GL_ARB_separate_shader_objects]      = EBhDisable;
    165     extensionBehavior[E_GL_ARB_compute_shader]               = EBhDisable;
    166     extensionBehavior[E_GL_ARB_tessellation_shader]          = EBhDisable;
    167     extensionBehavior[E_GL_ARB_enhanced_layouts]             = EBhDisable;
    168     extensionBehavior[E_GL_ARB_texture_cube_map_array]       = EBhDisable;
    169     extensionBehavior[E_GL_ARB_shader_texture_lod]           = EBhDisable;
    170     extensionBehavior[E_GL_ARB_explicit_attrib_location]     = EBhDisable;
    171     extensionBehavior[E_GL_ARB_shader_image_load_store]      = EBhDisable;
    172     extensionBehavior[E_GL_ARB_shader_atomic_counters]       = EBhDisable;
    173     extensionBehavior[E_GL_ARB_shader_draw_parameters]       = EBhDisable;
    174     extensionBehavior[E_GL_ARB_shader_group_vote]            = EBhDisable;
    175     extensionBehavior[E_GL_ARB_derivative_control]           = EBhDisable;
    176     extensionBehavior[E_GL_ARB_shader_texture_image_samples] = EBhDisable;
    177     extensionBehavior[E_GL_ARB_viewport_array]               = EBhDisable;
    178     extensionBehavior[E_GL_ARB_gpu_shader_int64]             = EBhDisable;
    179     extensionBehavior[E_GL_ARB_shader_ballot]                = EBhDisable;
    180     extensionBehavior[E_GL_ARB_sparse_texture2]              = EBhDisable;
    181     extensionBehavior[E_GL_ARB_sparse_texture_clamp]         = EBhDisable;
    182 //    extensionBehavior[E_GL_ARB_cull_distance]                = EBhDisable;    // present for 4.5, but need extension control over block members
    183 
    184     extensionBehavior[E_GL_EXT_shader_non_constant_global_initializers] = EBhDisable;
    185 
    186     // #line and #include
    187     extensionBehavior[E_GL_GOOGLE_cpp_style_line_directive]          = EBhDisable;
    188     extensionBehavior[E_GL_GOOGLE_include_directive]                 = EBhDisable;
    189 
    190     // AEP
    191     extensionBehavior[E_GL_ANDROID_extension_pack_es31a]             = EBhDisable;
    192     extensionBehavior[E_GL_KHR_blend_equation_advanced]              = EBhDisable;
    193     extensionBehavior[E_GL_OES_sample_variables]                     = EBhDisable;
    194     extensionBehavior[E_GL_OES_shader_image_atomic]                  = EBhDisable;
    195     extensionBehavior[E_GL_OES_shader_multisample_interpolation]     = EBhDisable;
    196     extensionBehavior[E_GL_OES_texture_storage_multisample_2d_array] = EBhDisable;
    197     extensionBehavior[E_GL_EXT_geometry_shader]                      = EBhDisable;
    198     extensionBehavior[E_GL_EXT_geometry_point_size]                  = EBhDisable;
    199     extensionBehavior[E_GL_EXT_gpu_shader5]                          = EBhDisable;
    200     extensionBehavior[E_GL_EXT_primitive_bounding_box]               = EBhDisable;
    201     extensionBehavior[E_GL_EXT_shader_io_blocks]                     = EBhDisable;
    202     extensionBehavior[E_GL_EXT_tessellation_shader]                  = EBhDisable;
    203     extensionBehavior[E_GL_EXT_tessellation_point_size]              = EBhDisable;
    204     extensionBehavior[E_GL_EXT_texture_buffer]                       = EBhDisable;
    205     extensionBehavior[E_GL_EXT_texture_cube_map_array]               = EBhDisable;
    206 
    207     // OES matching AEP
    208     extensionBehavior[E_GL_OES_geometry_shader]          = EBhDisable;
    209     extensionBehavior[E_GL_OES_geometry_point_size]      = EBhDisable;
    210     extensionBehavior[E_GL_OES_gpu_shader5]              = EBhDisable;
    211     extensionBehavior[E_GL_OES_primitive_bounding_box]   = EBhDisable;
    212     extensionBehavior[E_GL_OES_shader_io_blocks]         = EBhDisable;
    213     extensionBehavior[E_GL_OES_tessellation_shader]      = EBhDisable;
    214     extensionBehavior[E_GL_OES_tessellation_point_size]  = EBhDisable;
    215     extensionBehavior[E_GL_OES_texture_buffer]           = EBhDisable;
    216     extensionBehavior[E_GL_OES_texture_cube_map_array]   = EBhDisable;
    217 }
    218 
    219 // Get code that is not part of a shared symbol table, is specific to this shader,
    220 // or needed by the preprocessor (which does not use a shared symbol table).
    221 void TParseVersions::getPreamble(std::string& preamble)
    222 {
    223     if (profile == EEsProfile) {
    224         preamble =
    225             "#define GL_ES 1\n"
    226             "#define GL_FRAGMENT_PRECISION_HIGH 1\n"
    227             "#define GL_OES_texture_3D 1\n"
    228             "#define GL_OES_standard_derivatives 1\n"
    229             "#define GL_EXT_frag_depth 1\n"
    230             "#define GL_OES_EGL_image_external 1\n"
    231             "#define GL_EXT_shader_texture_lod 1\n"
    232 
    233             // AEP
    234             "#define GL_ANDROID_extension_pack_es31a 1\n"
    235             "#define GL_KHR_blend_equation_advanced 1\n"
    236             "#define GL_OES_sample_variables 1\n"
    237             "#define GL_OES_shader_image_atomic 1\n"
    238             "#define GL_OES_shader_multisample_interpolation 1\n"
    239             "#define GL_OES_texture_storage_multisample_2d_array 1\n"
    240             "#define GL_EXT_geometry_shader 1\n"
    241             "#define GL_EXT_geometry_point_size 1\n"
    242             "#define GL_EXT_gpu_shader5 1\n"
    243             "#define GL_EXT_primitive_bounding_box 1\n"
    244             "#define GL_EXT_shader_io_blocks 1\n"
    245             "#define GL_EXT_tessellation_shader 1\n"
    246             "#define GL_EXT_tessellation_point_size 1\n"
    247             "#define GL_EXT_texture_buffer 1\n"
    248             "#define GL_EXT_texture_cube_map_array 1\n"
    249 
    250             // OES matching AEP
    251             "#define GL_OES_geometry_shader 1\n"
    252             "#define GL_OES_geometry_point_size 1\n"
    253             "#define GL_OES_gpu_shader5 1\n"
    254             "#define GL_OES_primitive_bounding_box 1\n"
    255             "#define GL_OES_shader_io_blocks 1\n"
    256             "#define GL_OES_tessellation_shader 1\n"
    257             "#define GL_OES_tessellation_point_size 1\n"
    258             "#define GL_OES_texture_buffer 1\n"
    259             "#define GL_OES_texture_cube_map_array 1\n"
    260             "#define GL_EXT_shader_non_constant_global_initializers 1\n"
    261             ;
    262     } else {
    263         preamble =
    264             "#define GL_FRAGMENT_PRECISION_HIGH 1\n"
    265             "#define GL_ARB_texture_rectangle 1\n"
    266             "#define GL_ARB_shading_language_420pack 1\n"
    267             "#define GL_ARB_texture_gather 1\n"
    268             "#define GL_ARB_gpu_shader5 1\n"
    269             "#define GL_ARB_separate_shader_objects 1\n"
    270             "#define GL_ARB_compute_shader 1\n"
    271             "#define GL_ARB_tessellation_shader 1\n"
    272             "#define GL_ARB_enhanced_layouts 1\n"
    273             "#define GL_ARB_texture_cube_map_array 1\n"
    274             "#define GL_ARB_shader_texture_lod 1\n"
    275             "#define GL_ARB_explicit_attrib_location 1\n"
    276             "#define GL_ARB_shader_image_load_store 1\n"
    277             "#define GL_ARB_shader_atomic_counters 1\n"
    278             "#define GL_ARB_shader_draw_parameters 1\n"
    279             "#define GL_ARB_shader_group_vote 1\n"
    280             "#define GL_ARB_derivative_control 1\n"
    281             "#define GL_ARB_shader_texture_image_samples 1\n"
    282             "#define GL_ARB_viewport_array 1\n"
    283             "#define GL_ARB_gpu_shader_int64 1\n"
    284             "#define GL_ARB_shader_ballot 1\n"
    285             "#define GL_ARB_sparse_texture2 1\n"
    286             "#define GL_ARB_sparse_texture_clamp 1\n"
    287 //            "#define GL_ARB_cull_distance 1\n"    // present for 4.5, but need extension control over block members
    288             "#define GL_EXT_shader_non_constant_global_initializers 1\n"
    289             ;
    290     }
    291 
    292     // #line and #include
    293     preamble +=
    294             "#define GL_GOOGLE_cpp_style_line_directive 1\n"
    295             "#define GL_GOOGLE_include_directive 1\n"
    296             ;
    297 
    298     // #define VULKAN XXXX
    299     const int numberBufSize = 12;
    300     char numberBuf[numberBufSize];
    301     if (spvVersion.vulkan > 0) {
    302         preamble += "#define VULKAN ";
    303         snprintf(numberBuf, numberBufSize, "%d", spvVersion.vulkan);
    304         preamble += numberBuf;
    305         preamble += "\n";
    306     }
    307     // #define GL_SPIRV XXXX
    308     if (spvVersion.openGl > 0) {
    309         preamble += "#define GL_SPIRV ";
    310         snprintf(numberBuf, numberBufSize, "%d", spvVersion.openGl);
    311         preamble += numberBuf;
    312         preamble += "\n";
    313     }
    314 
    315 }
    316 
    317 //
    318 // When to use requireProfile():
    319 //
    320 //     Use if only some profiles support a feature.  However, if within a profile the feature
    321 //     is version or extension specific, follow this call with calls to profileRequires().
    322 //
    323 // Operation:  If the current profile is not one of the profileMask,
    324 // give an error message.
    325 //
    326 void TParseVersions::requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc)
    327 {
    328     if (! (profile & profileMask))
    329         error(loc, "not supported with this profile:", featureDesc, ProfileName(profile));
    330 }
    331 
    332 //
    333 // Map from stage enum to externally readable text name.
    334 //
    335 const char* StageName(EShLanguage stage)
    336 {
    337     switch(stage) {
    338     case EShLangVertex:         return "vertex";
    339     case EShLangTessControl:    return "tessellation control";
    340     case EShLangTessEvaluation: return "tessellation evaluation";
    341     case EShLangGeometry:       return "geometry";
    342     case EShLangFragment:       return "fragment";
    343     case EShLangCompute:        return "compute";
    344     default:                    return "unknown stage";
    345     }
    346 }
    347 
    348 //
    349 // When to use profileRequires():
    350 //
    351 //     If a set of profiles have the same requirements for what version or extensions
    352 //     are needed to support a feature.
    353 //
    354 //     It must be called for each profile that needs protection.  Use requireProfile() first
    355 //     to reduce that set of profiles.
    356 //
    357 // Operation: Will issue warnings/errors based on the current profile, version, and extension
    358 // behaviors.  It only checks extensions when the current profile is one of the profileMask.
    359 //
    360 // A minVersion of 0 means no version of the profileMask support this in core,
    361 // the extension must be present.
    362 //
    363 
    364 // entry point that takes multiple extensions
    365 void TParseVersions::profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions, const char* const extensions[], const char* featureDesc)
    366 {
    367     if (profile & profileMask) {
    368         bool okay = false;
    369         if (minVersion > 0 && version >= minVersion)
    370             okay = true;
    371         for (int i = 0; i < numExtensions; ++i) {
    372             switch (getExtensionBehavior(extensions[i])) {
    373             case EBhWarn:
    374                 infoSink.info.message(EPrefixWarning, ("extension " + TString(extensions[i]) + " is being used for " + featureDesc).c_str(), loc);
    375                 // fall through
    376             case EBhRequire:
    377             case EBhEnable:
    378                 okay = true;
    379                 break;
    380             default: break; // some compilers want this
    381             }
    382         }
    383 
    384         if (! okay)
    385             error(loc, "not supported for this version or the enabled extensions", featureDesc, "");
    386     }
    387 }
    388 
    389 // entry point for the above that takes a single extension
    390 void TParseVersions::profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, const char* extension, const char* featureDesc)
    391 {
    392     profileRequires(loc, profileMask, minVersion, extension ? 1 : 0, &extension, featureDesc);
    393 }
    394 
    395 //
    396 // When to use requireStage()
    397 //
    398 //     If only some stages support a feature.
    399 //
    400 // Operation: If the current stage is not present, give an error message.
    401 //
    402 void TParseVersions::requireStage(const TSourceLoc& loc, EShLanguageMask languageMask, const char* featureDesc)
    403 {
    404     if (((1 << language) & languageMask) == 0)
    405         error(loc, "not supported in this stage:", featureDesc, StageName(language));
    406 }
    407 
    408 // If only one stage supports a feature, this can be called.  But, all supporting stages
    409 // must be specified with one call.
    410 void TParseVersions::requireStage(const TSourceLoc& loc, EShLanguage stage, const char* featureDesc)
    411 {
    412     requireStage(loc, static_cast<EShLanguageMask>(1 << stage), featureDesc);
    413 }
    414 
    415 //
    416 // Within a set of profiles, see if a feature is deprecated and give an error or warning based on whether
    417 // a future compatibility context is being use.
    418 //
    419 void TParseVersions::checkDeprecated(const TSourceLoc& loc, int profileMask, int depVersion, const char* featureDesc)
    420 {
    421     if (profile & profileMask) {
    422         if (version >= depVersion) {
    423             if (forwardCompatible)
    424                 error(loc, "deprecated, may be removed in future release", featureDesc, "");
    425             else if (! suppressWarnings())
    426                 infoSink.info.message(EPrefixWarning, (TString(featureDesc) + " deprecated in version " +
    427                                                        String(depVersion) + "; may be removed in future release").c_str(), loc);
    428         }
    429     }
    430 }
    431 
    432 //
    433 // Within a set of profiles, see if a feature has now been removed and if so, give an error.
    434 // The version argument is the first version no longer having the feature.
    435 //
    436 void TParseVersions::requireNotRemoved(const TSourceLoc& loc, int profileMask, int removedVersion, const char* featureDesc)
    437 {
    438     if (profile & profileMask) {
    439         if (version >= removedVersion) {
    440             const int maxSize = 60;
    441             char buf[maxSize];
    442             snprintf(buf, maxSize, "%s profile; removed in version %d", ProfileName(profile), removedVersion);
    443             error(loc, "no longer supported in", featureDesc, buf);
    444         }
    445     }
    446 }
    447 
    448 // Returns true if at least one of the extensions in the extensions parameter is requested. Otherwise, returns false.
    449 // Warns appropriately if the requested behavior of an extension is "warn".
    450 bool TParseVersions::checkExtensionsRequested(const TSourceLoc& loc, int numExtensions, const char* const extensions[], const char* featureDesc)
    451 {
    452     // First, see if any of the extensions are enabled
    453     for (int i = 0; i < numExtensions; ++i) {
    454         TExtensionBehavior behavior = getExtensionBehavior(extensions[i]);
    455         if (behavior == EBhEnable || behavior == EBhRequire)
    456             return true;
    457     }
    458 
    459     // See if any extensions want to give a warning on use; give warnings for all such extensions
    460     bool warned = false;
    461     for (int i = 0; i < numExtensions; ++i) {
    462         TExtensionBehavior behavior = getExtensionBehavior(extensions[i]);
    463         if (behavior == EBhDisable && relaxedErrors()) {
    464             infoSink.info.message(EPrefixWarning, "The following extension must be enabled to use this feature:", loc);
    465             behavior = EBhWarn;
    466         }
    467         if (behavior == EBhWarn) {
    468             infoSink.info.message(EPrefixWarning, ("extension " + TString(extensions[i]) + " is being used for " + featureDesc).c_str(), loc);
    469             warned = true;
    470         }
    471     }
    472     if (warned)
    473         return true;
    474     return false;
    475 }
    476 
    477 //
    478 // Use when there are no profile/version to check, it's just an error if one of the
    479 // extensions is not present.
    480 //
    481 void TParseVersions::requireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[], const char* featureDesc)
    482 {
    483     if (checkExtensionsRequested(loc, numExtensions, extensions, featureDesc)) return;
    484 
    485     // If we get this far, give errors explaining what extensions are needed
    486     if (numExtensions == 1)
    487         error(loc, "required extension not requested:", featureDesc, extensions[0]);
    488     else {
    489         error(loc, "required extension not requested:", featureDesc, "Possible extensions include:");
    490         for (int i = 0; i < numExtensions; ++i)
    491             infoSink.info.message(EPrefixNone, extensions[i]);
    492     }
    493 }
    494 
    495 //
    496 // Use by preprocessor when there are no profile/version to check, it's just an error if one of the
    497 // extensions is not present.
    498 //
    499 void TParseVersions::ppRequireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[], const char* featureDesc)
    500 {
    501     if (checkExtensionsRequested(loc, numExtensions, extensions, featureDesc)) return;
    502 
    503     // If we get this far, give errors explaining what extensions are needed
    504     if (numExtensions == 1)
    505         ppError(loc, "required extension not requested:", featureDesc, extensions[0]);
    506     else {
    507         ppError(loc, "required extension not requested:", featureDesc, "Possible extensions include:");
    508         for (int i = 0; i < numExtensions; ++i)
    509             infoSink.info.message(EPrefixNone, extensions[i]);
    510     }
    511 }
    512 
    513 TExtensionBehavior TParseVersions::getExtensionBehavior(const char* extension)
    514 {
    515     auto iter = extensionBehavior.find(TString(extension));
    516     if (iter == extensionBehavior.end())
    517         return EBhMissing;
    518     else
    519         return iter->second;
    520 }
    521 
    522 // Returns true if the given extension is set to enable, require, or warn.
    523 bool TParseVersions::extensionTurnedOn(const char* const extension)
    524 {
    525       switch (getExtensionBehavior(extension)) {
    526       case EBhEnable:
    527       case EBhRequire:
    528       case EBhWarn:
    529           return true;
    530       default:
    531           break;
    532       }
    533       return false;
    534 }
    535 // See if any of the extensions are set to enable, require, or warn.
    536 bool TParseVersions::extensionsTurnedOn(int numExtensions, const char* const extensions[])
    537 {
    538     for (int i = 0; i < numExtensions; ++i) {
    539         if (extensionTurnedOn(extensions[i])) return true;
    540     }
    541     return false;
    542 }
    543 
    544 //
    545 // Change the current state of an extension's behavior.
    546 //
    547 void TParseVersions::updateExtensionBehavior(int line, const char* extension, const char* behaviorString)
    548 {
    549     // Translate from text string of extension's behavior to an enum.
    550     TExtensionBehavior behavior = EBhDisable;
    551     if (! strcmp("require", behaviorString))
    552         behavior = EBhRequire;
    553     else if (! strcmp("enable", behaviorString))
    554         behavior = EBhEnable;
    555     else if (! strcmp("disable", behaviorString))
    556         behavior = EBhDisable;
    557     else if (! strcmp("warn", behaviorString))
    558         behavior = EBhWarn;
    559     else {
    560         error(getCurrentLoc(), "behavior not supported:", "#extension", behaviorString);
    561         return;
    562     }
    563 
    564     // update the requested extension
    565     updateExtensionBehavior(extension, behavior);
    566 
    567     // see if need to propagate to implicitly modified things
    568     if (strcmp(extension, "GL_ANDROID_extension_pack_es31a") == 0) {
    569         // to everything in AEP
    570         updateExtensionBehavior(line, "GL_KHR_blend_equation_advanced", behaviorString);
    571         updateExtensionBehavior(line, "GL_OES_sample_variables", behaviorString);
    572         updateExtensionBehavior(line, "GL_OES_shader_image_atomic", behaviorString);
    573         updateExtensionBehavior(line, "GL_OES_shader_multisample_interpolation", behaviorString);
    574         updateExtensionBehavior(line, "GL_OES_texture_storage_multisample_2d_array", behaviorString);
    575         updateExtensionBehavior(line, "GL_EXT_geometry_shader", behaviorString);
    576         updateExtensionBehavior(line, "GL_EXT_gpu_shader5", behaviorString);
    577         updateExtensionBehavior(line, "GL_EXT_primitive_bounding_box", behaviorString);
    578         updateExtensionBehavior(line, "GL_EXT_shader_io_blocks", behaviorString);
    579         updateExtensionBehavior(line, "GL_EXT_tessellation_shader", behaviorString);
    580         updateExtensionBehavior(line, "GL_EXT_texture_buffer", behaviorString);
    581         updateExtensionBehavior(line, "GL_EXT_texture_cube_map_array", behaviorString);
    582     }
    583     // geometry to io_blocks
    584     else if (strcmp(extension, "GL_EXT_geometry_shader") == 0)
    585         updateExtensionBehavior(line, "GL_EXT_shader_io_blocks", behaviorString);
    586     else if (strcmp(extension, "GL_OES_geometry_shader") == 0)
    587         updateExtensionBehavior(line, "GL_OES_shader_io_blocks", behaviorString);
    588     // tessellation to io_blocks
    589     else if (strcmp(extension, "GL_EXT_tessellation_shader") == 0)
    590         updateExtensionBehavior(line, "GL_EXT_shader_io_blocks", behaviorString);
    591     else if (strcmp(extension, "GL_OES_tessellation_shader") == 0)
    592         updateExtensionBehavior(line, "GL_OES_shader_io_blocks", behaviorString);
    593     else if (strcmp(extension, "GL_GOOGLE_include_directive") == 0)
    594         updateExtensionBehavior(line, "GL_GOOGLE_cpp_style_line_directive", behaviorString);
    595 }
    596 
    597 void TParseVersions::updateExtensionBehavior(const char* extension, TExtensionBehavior behavior)
    598 {
    599     // Update the current behavior
    600     if (strcmp(extension, "all") == 0) {
    601         // special case for the 'all' extension; apply it to every extension present
    602         if (behavior == EBhRequire || behavior == EBhEnable) {
    603             error(getCurrentLoc(), "extension 'all' cannot have 'require' or 'enable' behavior", "#extension", "");
    604             return;
    605         } else {
    606             for (auto iter = extensionBehavior.begin(); iter != extensionBehavior.end(); ++iter)
    607                 iter->second = behavior;
    608         }
    609     } else {
    610         // Do the update for this single extension
    611         auto iter = extensionBehavior.find(TString(extension));
    612         if (iter == extensionBehavior.end()) {
    613             switch (behavior) {
    614             case EBhRequire:
    615                 error(getCurrentLoc(), "extension not supported:", "#extension", extension);
    616                 break;
    617             case EBhEnable:
    618             case EBhWarn:
    619             case EBhDisable:
    620                 warn(getCurrentLoc(), "extension not supported:", "#extension", extension);
    621                 break;
    622             default:
    623                 assert(0 && "unexpected behavior");
    624             }
    625 
    626             return;
    627         } else {
    628             if (iter->second == EBhDisablePartial)
    629                 warn(getCurrentLoc(), "extension is only partially supported:", "#extension", extension);
    630             if (behavior == EBhEnable || behavior == EBhRequire)
    631                 intermediate.addRequestedExtension(extension);
    632             iter->second = behavior;
    633         }
    634     }
    635 }
    636 
    637 // Call for any operation needing full GLSL integer data-type support.
    638 void TParseVersions::fullIntegerCheck(const TSourceLoc& loc, const char* op)
    639 {
    640     profileRequires(loc, ENoProfile, 130, nullptr, op);
    641     profileRequires(loc, EEsProfile, 300, nullptr, op);
    642 }
    643 
    644 // Call for any operation needing GLSL double data-type support.
    645 void TParseVersions::doubleCheck(const TSourceLoc& loc, const char* op)
    646 {
    647     requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
    648     profileRequires(loc, ECoreProfile, 400, nullptr, op);
    649     profileRequires(loc, ECompatibilityProfile, 400, nullptr, op);
    650 }
    651 
    652 // Call for any operation needing GLSL 64-bit integer data-type support.
    653 void TParseVersions::int64Check(const TSourceLoc& loc, const char* op, bool builtIn)
    654 {
    655     if (! builtIn) {
    656         requireExtensions(loc, 1, &E_GL_ARB_gpu_shader_int64, "shader int64");
    657         requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
    658         profileRequires(loc, ECoreProfile, 450, nullptr, op);
    659         profileRequires(loc, ECompatibilityProfile, 450, nullptr, op);
    660     }
    661 }
    662 
    663 // Call for any operation removed because SPIR-V is in use.
    664 void TParseVersions::spvRemoved(const TSourceLoc& loc, const char* op)
    665 {
    666     if (spvVersion.spv != 0)
    667         error(loc, "not allowed when generating SPIR-V", op, "");
    668 }
    669 
    670 // Call for any operation removed because Vulkan SPIR-V is being generated.
    671 void TParseVersions::vulkanRemoved(const TSourceLoc& loc, const char* op)
    672 {
    673     if (spvVersion.vulkan >= 100)
    674         error(loc, "not allowed when using GLSL for Vulkan", op, "");
    675 }
    676 
    677 // Call for any operation that requires Vulkan.
    678 void TParseVersions::requireVulkan(const TSourceLoc& loc, const char* op)
    679 {
    680     if (spvVersion.vulkan == 0)
    681         error(loc, "only allowed when using GLSL for Vulkan", op, "");
    682 }
    683 
    684 // Call for any operation that requires SPIR-V.
    685 void TParseVersions::requireSpv(const TSourceLoc& loc, const char* op)
    686 {
    687     if (spvVersion.spv == 0)
    688         error(loc, "only allowed when generating SPIR-V", op, "");
    689 }
    690 
    691 } // end namespace glslang
    692