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     extensionBehavior[E_GL_EXT_shadow_samplers]              = EBhDisable;
    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_shader_stencil_export]        = EBhDisable;
    183 //    extensionBehavior[E_GL_ARB_cull_distance]                = EBhDisable;    // present for 4.5, but need extension control over block members
    184     extensionBehavior[E_GL_ARB_post_depth_coverage]          = EBhDisable;
    185     extensionBehavior[E_GL_ARB_shader_viewport_layer_array]  = EBhDisable;
    186 
    187     extensionBehavior[E_GL_EXT_shader_non_constant_global_initializers] = EBhDisable;
    188     extensionBehavior[E_GL_EXT_shader_image_load_formatted]             = EBhDisable;
    189     extensionBehavior[E_GL_EXT_post_depth_coverage]                     = EBhDisable;
    190 
    191     // #line and #include
    192     extensionBehavior[E_GL_GOOGLE_cpp_style_line_directive]          = EBhDisable;
    193     extensionBehavior[E_GL_GOOGLE_include_directive]                 = EBhDisable;
    194 
    195 #ifdef AMD_EXTENSIONS
    196     extensionBehavior[E_GL_AMD_shader_ballot]                        = EBhDisable;
    197     extensionBehavior[E_GL_AMD_shader_trinary_minmax]                = EBhDisable;
    198     extensionBehavior[E_GL_AMD_shader_explicit_vertex_parameter]     = EBhDisable;
    199     extensionBehavior[E_GL_AMD_gcn_shader]                           = EBhDisable;
    200     extensionBehavior[E_GL_AMD_gpu_shader_half_float]                = EBhDisable;
    201     extensionBehavior[E_GL_AMD_texture_gather_bias_lod]              = EBhDisable;
    202     extensionBehavior[E_GL_AMD_gpu_shader_int16]                     = EBhDisable;
    203     extensionBehavior[E_GL_AMD_shader_image_load_store_lod]          = EBhDisable;
    204 #endif
    205 
    206 #ifdef NV_EXTENSIONS
    207     extensionBehavior[E_GL_NV_sample_mask_override_coverage]         = EBhDisable;
    208     extensionBehavior[E_SPV_NV_geometry_shader_passthrough]          = EBhDisable;
    209     extensionBehavior[E_GL_NV_viewport_array2]                       = EBhDisable;
    210     extensionBehavior[E_GL_NV_stereo_view_rendering]                 = EBhDisable;
    211     extensionBehavior[E_GL_NVX_multiview_per_view_attributes]        = EBhDisable;
    212 #endif
    213 
    214     // AEP
    215     extensionBehavior[E_GL_ANDROID_extension_pack_es31a]             = EBhDisable;
    216     extensionBehavior[E_GL_KHR_blend_equation_advanced]              = EBhDisable;
    217     extensionBehavior[E_GL_OES_sample_variables]                     = EBhDisable;
    218     extensionBehavior[E_GL_OES_shader_image_atomic]                  = EBhDisable;
    219     extensionBehavior[E_GL_OES_shader_multisample_interpolation]     = EBhDisable;
    220     extensionBehavior[E_GL_OES_texture_storage_multisample_2d_array] = EBhDisable;
    221     extensionBehavior[E_GL_EXT_geometry_shader]                      = EBhDisable;
    222     extensionBehavior[E_GL_EXT_geometry_point_size]                  = EBhDisable;
    223     extensionBehavior[E_GL_EXT_gpu_shader5]                          = EBhDisable;
    224     extensionBehavior[E_GL_EXT_primitive_bounding_box]               = EBhDisable;
    225     extensionBehavior[E_GL_EXT_shader_io_blocks]                     = EBhDisable;
    226     extensionBehavior[E_GL_EXT_tessellation_shader]                  = EBhDisable;
    227     extensionBehavior[E_GL_EXT_tessellation_point_size]              = EBhDisable;
    228     extensionBehavior[E_GL_EXT_texture_buffer]                       = EBhDisable;
    229     extensionBehavior[E_GL_EXT_texture_cube_map_array]               = EBhDisable;
    230 
    231     // OES matching AEP
    232     extensionBehavior[E_GL_OES_geometry_shader]          = EBhDisable;
    233     extensionBehavior[E_GL_OES_geometry_point_size]      = EBhDisable;
    234     extensionBehavior[E_GL_OES_gpu_shader5]              = EBhDisable;
    235     extensionBehavior[E_GL_OES_primitive_bounding_box]   = EBhDisable;
    236     extensionBehavior[E_GL_OES_shader_io_blocks]         = EBhDisable;
    237     extensionBehavior[E_GL_OES_tessellation_shader]      = EBhDisable;
    238     extensionBehavior[E_GL_OES_tessellation_point_size]  = EBhDisable;
    239     extensionBehavior[E_GL_OES_texture_buffer]           = EBhDisable;
    240     extensionBehavior[E_GL_OES_texture_cube_map_array]   = EBhDisable;
    241 
    242     // EXT extensions
    243     extensionBehavior[E_GL_EXT_device_group]             = EBhDisable;
    244     extensionBehavior[E_GL_EXT_multiview]                = EBhDisable;
    245 
    246     // OVR extensions
    247     extensionBehavior[E_GL_OVR_multiview]                = EBhDisable;
    248     extensionBehavior[E_GL_OVR_multiview2]               = EBhDisable;
    249 }
    250 
    251 // Get code that is not part of a shared symbol table, is specific to this shader,
    252 // or needed by the preprocessor (which does not use a shared symbol table).
    253 void TParseVersions::getPreamble(std::string& preamble)
    254 {
    255     if (profile == EEsProfile) {
    256         preamble =
    257             "#define GL_ES 1\n"
    258             "#define GL_FRAGMENT_PRECISION_HIGH 1\n"
    259             "#define GL_OES_texture_3D 1\n"
    260             "#define GL_OES_standard_derivatives 1\n"
    261             "#define GL_EXT_frag_depth 1\n"
    262             "#define GL_OES_EGL_image_external 1\n"
    263             "#define GL_EXT_shader_texture_lod 1\n"
    264             "#define GL_EXT_shadow_samplers 1\n"
    265 
    266             // AEP
    267             "#define GL_ANDROID_extension_pack_es31a 1\n"
    268             "#define GL_KHR_blend_equation_advanced 1\n"
    269             "#define GL_OES_sample_variables 1\n"
    270             "#define GL_OES_shader_image_atomic 1\n"
    271             "#define GL_OES_shader_multisample_interpolation 1\n"
    272             "#define GL_OES_texture_storage_multisample_2d_array 1\n"
    273             "#define GL_EXT_geometry_shader 1\n"
    274             "#define GL_EXT_geometry_point_size 1\n"
    275             "#define GL_EXT_gpu_shader5 1\n"
    276             "#define GL_EXT_primitive_bounding_box 1\n"
    277             "#define GL_EXT_shader_io_blocks 1\n"
    278             "#define GL_EXT_tessellation_shader 1\n"
    279             "#define GL_EXT_tessellation_point_size 1\n"
    280             "#define GL_EXT_texture_buffer 1\n"
    281             "#define GL_EXT_texture_cube_map_array 1\n"
    282 
    283             // OES matching AEP
    284             "#define GL_OES_geometry_shader 1\n"
    285             "#define GL_OES_geometry_point_size 1\n"
    286             "#define GL_OES_gpu_shader5 1\n"
    287             "#define GL_OES_primitive_bounding_box 1\n"
    288             "#define GL_OES_shader_io_blocks 1\n"
    289             "#define GL_OES_tessellation_shader 1\n"
    290             "#define GL_OES_tessellation_point_size 1\n"
    291             "#define GL_OES_texture_buffer 1\n"
    292             "#define GL_OES_texture_cube_map_array 1\n"
    293             "#define GL_EXT_shader_non_constant_global_initializers 1\n"
    294             ;
    295     } else {
    296         preamble =
    297             "#define GL_FRAGMENT_PRECISION_HIGH 1\n"
    298             "#define GL_ARB_texture_rectangle 1\n"
    299             "#define GL_ARB_shading_language_420pack 1\n"
    300             "#define GL_ARB_texture_gather 1\n"
    301             "#define GL_ARB_gpu_shader5 1\n"
    302             "#define GL_ARB_separate_shader_objects 1\n"
    303             "#define GL_ARB_compute_shader 1\n"
    304             "#define GL_ARB_tessellation_shader 1\n"
    305             "#define GL_ARB_enhanced_layouts 1\n"
    306             "#define GL_ARB_texture_cube_map_array 1\n"
    307             "#define GL_ARB_shader_texture_lod 1\n"
    308             "#define GL_ARB_explicit_attrib_location 1\n"
    309             "#define GL_ARB_shader_image_load_store 1\n"
    310             "#define GL_ARB_shader_atomic_counters 1\n"
    311             "#define GL_ARB_shader_draw_parameters 1\n"
    312             "#define GL_ARB_shader_group_vote 1\n"
    313             "#define GL_ARB_derivative_control 1\n"
    314             "#define GL_ARB_shader_texture_image_samples 1\n"
    315             "#define GL_ARB_viewport_array 1\n"
    316             "#define GL_ARB_gpu_shader_int64 1\n"
    317             "#define GL_ARB_shader_ballot 1\n"
    318             "#define GL_ARB_sparse_texture2 1\n"
    319             "#define GL_ARB_sparse_texture_clamp 1\n"
    320             "#define GL_ARB_shader_stencil_export 1\n"
    321 //            "#define GL_ARB_cull_distance 1\n"    // present for 4.5, but need extension control over block members
    322             "#define GL_ARB_post_depth_coverage 1\n"
    323             "#define GL_EXT_shader_non_constant_global_initializers 1\n"
    324             "#define GL_EXT_shader_image_load_formatted 1\n"
    325             "#define GL_EXT_post_depth_coverage 1\n"
    326 
    327 #ifdef AMD_EXTENSIONS
    328             "#define GL_AMD_shader_ballot 1\n"
    329             "#define GL_AMD_shader_trinary_minmax 1\n"
    330             "#define GL_AMD_shader_explicit_vertex_parameter 1\n"
    331             "#define GL_AMD_gcn_shader 1\n"
    332             "#define GL_AMD_gpu_shader_half_float 1\n"
    333             "#define GL_AMD_texture_gather_bias_lod 1\n"
    334             "#define GL_AMD_gpu_shader_int16 1\n"
    335             "#define GL_AMD_shader_image_load_store_lod 1\n"
    336 #endif
    337 
    338 #ifdef NV_EXTENSIONS
    339             "#define GL_NV_sample_mask_override_coverage 1\n"
    340             "#define GL_NV_geometry_shader_passthrough 1\n"
    341             "#define GL_NV_viewport_array2 1\n"
    342 #endif
    343             ;
    344 
    345         if (version >= 150) {
    346             // define GL_core_profile and GL_compatibility_profile
    347             preamble += "#define GL_core_profile 1\n";
    348 
    349             if (profile == ECompatibilityProfile)
    350                 preamble += "#define GL_compatibility_profile 1\n";
    351         }
    352     }
    353 
    354     if ((profile != EEsProfile && version >= 140) ||
    355         (profile == EEsProfile && version >= 310)) {
    356         preamble +=
    357             "#define GL_EXT_device_group 1\n"
    358             "#define GL_EXT_multiview 1\n"
    359             ;
    360     }
    361 
    362     if (version >= 300 /* both ES and non-ES */) {
    363         preamble +=
    364             "#define GL_OVR_multiview 1\n"
    365             "#define GL_OVR_multiview2 1\n"
    366             ;
    367     }
    368 
    369     // #line and #include
    370     preamble +=
    371             "#define GL_GOOGLE_cpp_style_line_directive 1\n"
    372             "#define GL_GOOGLE_include_directive 1\n"
    373             ;
    374 
    375     // #define VULKAN XXXX
    376     const int numberBufSize = 12;
    377     char numberBuf[numberBufSize];
    378     if (spvVersion.vulkanGlsl > 0) {
    379         preamble += "#define VULKAN ";
    380         snprintf(numberBuf, numberBufSize, "%d", spvVersion.vulkanGlsl);
    381         preamble += numberBuf;
    382         preamble += "\n";
    383     }
    384     // #define GL_SPIRV XXXX
    385     if (spvVersion.openGl > 0) {
    386         preamble += "#define GL_SPIRV ";
    387         snprintf(numberBuf, numberBufSize, "%d", spvVersion.openGl);
    388         preamble += numberBuf;
    389         preamble += "\n";
    390     }
    391 
    392 }
    393 
    394 //
    395 // When to use requireProfile():
    396 //
    397 //     Use if only some profiles support a feature.  However, if within a profile the feature
    398 //     is version or extension specific, follow this call with calls to profileRequires().
    399 //
    400 // Operation:  If the current profile is not one of the profileMask,
    401 // give an error message.
    402 //
    403 void TParseVersions::requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc)
    404 {
    405     if (! (profile & profileMask))
    406         error(loc, "not supported with this profile:", featureDesc, ProfileName(profile));
    407 }
    408 
    409 //
    410 // Map from stage enum to externally readable text name.
    411 //
    412 const char* StageName(EShLanguage stage)
    413 {
    414     switch(stage) {
    415     case EShLangVertex:         return "vertex";
    416     case EShLangTessControl:    return "tessellation control";
    417     case EShLangTessEvaluation: return "tessellation evaluation";
    418     case EShLangGeometry:       return "geometry";
    419     case EShLangFragment:       return "fragment";
    420     case EShLangCompute:        return "compute";
    421     default:                    return "unknown stage";
    422     }
    423 }
    424 
    425 //
    426 // When to use profileRequires():
    427 //
    428 //     If a set of profiles have the same requirements for what version or extensions
    429 //     are needed to support a feature.
    430 //
    431 //     It must be called for each profile that needs protection.  Use requireProfile() first
    432 //     to reduce that set of profiles.
    433 //
    434 // Operation: Will issue warnings/errors based on the current profile, version, and extension
    435 // behaviors.  It only checks extensions when the current profile is one of the profileMask.
    436 //
    437 // A minVersion of 0 means no version of the profileMask support this in core,
    438 // the extension must be present.
    439 //
    440 
    441 // entry point that takes multiple extensions
    442 void TParseVersions::profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions, const char* const extensions[], const char* featureDesc)
    443 {
    444     if (profile & profileMask) {
    445         bool okay = false;
    446         if (minVersion > 0 && version >= minVersion)
    447             okay = true;
    448         for (int i = 0; i < numExtensions; ++i) {
    449             switch (getExtensionBehavior(extensions[i])) {
    450             case EBhWarn:
    451                 infoSink.info.message(EPrefixWarning, ("extension " + TString(extensions[i]) + " is being used for " + featureDesc).c_str(), loc);
    452                 // fall through
    453             case EBhRequire:
    454             case EBhEnable:
    455                 okay = true;
    456                 break;
    457             default: break; // some compilers want this
    458             }
    459         }
    460 
    461         if (! okay)
    462             error(loc, "not supported for this version or the enabled extensions", featureDesc, "");
    463     }
    464 }
    465 
    466 // entry point for the above that takes a single extension
    467 void TParseVersions::profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, const char* extension, const char* featureDesc)
    468 {
    469     profileRequires(loc, profileMask, minVersion, extension ? 1 : 0, &extension, featureDesc);
    470 }
    471 
    472 //
    473 // When to use requireStage()
    474 //
    475 //     If only some stages support a feature.
    476 //
    477 // Operation: If the current stage is not present, give an error message.
    478 //
    479 void TParseVersions::requireStage(const TSourceLoc& loc, EShLanguageMask languageMask, const char* featureDesc)
    480 {
    481     if (((1 << language) & languageMask) == 0)
    482         error(loc, "not supported in this stage:", featureDesc, StageName(language));
    483 }
    484 
    485 // If only one stage supports a feature, this can be called.  But, all supporting stages
    486 // must be specified with one call.
    487 void TParseVersions::requireStage(const TSourceLoc& loc, EShLanguage stage, const char* featureDesc)
    488 {
    489     requireStage(loc, static_cast<EShLanguageMask>(1 << stage), featureDesc);
    490 }
    491 
    492 //
    493 // Within a set of profiles, see if a feature is deprecated and give an error or warning based on whether
    494 // a future compatibility context is being use.
    495 //
    496 void TParseVersions::checkDeprecated(const TSourceLoc& loc, int profileMask, int depVersion, const char* featureDesc)
    497 {
    498     if (profile & profileMask) {
    499         if (version >= depVersion) {
    500             if (forwardCompatible)
    501                 error(loc, "deprecated, may be removed in future release", featureDesc, "");
    502             else if (! suppressWarnings())
    503                 infoSink.info.message(EPrefixWarning, (TString(featureDesc) + " deprecated in version " +
    504                                                        String(depVersion) + "; may be removed in future release").c_str(), loc);
    505         }
    506     }
    507 }
    508 
    509 //
    510 // Within a set of profiles, see if a feature has now been removed and if so, give an error.
    511 // The version argument is the first version no longer having the feature.
    512 //
    513 void TParseVersions::requireNotRemoved(const TSourceLoc& loc, int profileMask, int removedVersion, const char* featureDesc)
    514 {
    515     if (profile & profileMask) {
    516         if (version >= removedVersion) {
    517             const int maxSize = 60;
    518             char buf[maxSize];
    519             snprintf(buf, maxSize, "%s profile; removed in version %d", ProfileName(profile), removedVersion);
    520             error(loc, "no longer supported in", featureDesc, buf);
    521         }
    522     }
    523 }
    524 
    525 void TParseVersions::unimplemented(const TSourceLoc& loc, const char* featureDesc)
    526 {
    527     error(loc, "feature not yet implemented", featureDesc, "");
    528 }
    529 
    530 // Returns true if at least one of the extensions in the extensions parameter is requested. Otherwise, returns false.
    531 // Warns appropriately if the requested behavior of an extension is "warn".
    532 bool TParseVersions::checkExtensionsRequested(const TSourceLoc& loc, int numExtensions, const char* const extensions[], const char* featureDesc)
    533 {
    534     // First, see if any of the extensions are enabled
    535     for (int i = 0; i < numExtensions; ++i) {
    536         TExtensionBehavior behavior = getExtensionBehavior(extensions[i]);
    537         if (behavior == EBhEnable || behavior == EBhRequire)
    538             return true;
    539     }
    540 
    541     // See if any extensions want to give a warning on use; give warnings for all such extensions
    542     bool warned = false;
    543     for (int i = 0; i < numExtensions; ++i) {
    544         TExtensionBehavior behavior = getExtensionBehavior(extensions[i]);
    545         if (behavior == EBhDisable && relaxedErrors()) {
    546             infoSink.info.message(EPrefixWarning, "The following extension must be enabled to use this feature:", loc);
    547             behavior = EBhWarn;
    548         }
    549         if (behavior == EBhWarn) {
    550             infoSink.info.message(EPrefixWarning, ("extension " + TString(extensions[i]) + " is being used for " + featureDesc).c_str(), loc);
    551             warned = true;
    552         }
    553     }
    554     if (warned)
    555         return true;
    556     return false;
    557 }
    558 
    559 //
    560 // Use when there are no profile/version to check, it's just an error if one of the
    561 // extensions is not present.
    562 //
    563 void TParseVersions::requireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[], const char* featureDesc)
    564 {
    565     if (checkExtensionsRequested(loc, numExtensions, extensions, featureDesc)) return;
    566 
    567     // If we get this far, give errors explaining what extensions are needed
    568     if (numExtensions == 1)
    569         error(loc, "required extension not requested:", featureDesc, extensions[0]);
    570     else {
    571         error(loc, "required extension not requested:", featureDesc, "Possible extensions include:");
    572         for (int i = 0; i < numExtensions; ++i)
    573             infoSink.info.message(EPrefixNone, extensions[i]);
    574     }
    575 }
    576 
    577 //
    578 // Use by preprocessor when there are no profile/version to check, it's just an error if one of the
    579 // extensions is not present.
    580 //
    581 void TParseVersions::ppRequireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[], const char* featureDesc)
    582 {
    583     if (checkExtensionsRequested(loc, numExtensions, extensions, featureDesc)) return;
    584 
    585     // If we get this far, give errors explaining what extensions are needed
    586     if (numExtensions == 1)
    587         ppError(loc, "required extension not requested:", featureDesc, extensions[0]);
    588     else {
    589         ppError(loc, "required extension not requested:", featureDesc, "Possible extensions include:");
    590         for (int i = 0; i < numExtensions; ++i)
    591             infoSink.info.message(EPrefixNone, extensions[i]);
    592     }
    593 }
    594 
    595 TExtensionBehavior TParseVersions::getExtensionBehavior(const char* extension)
    596 {
    597     auto iter = extensionBehavior.find(TString(extension));
    598     if (iter == extensionBehavior.end())
    599         return EBhMissing;
    600     else
    601         return iter->second;
    602 }
    603 
    604 // Returns true if the given extension is set to enable, require, or warn.
    605 bool TParseVersions::extensionTurnedOn(const char* const extension)
    606 {
    607       switch (getExtensionBehavior(extension)) {
    608       case EBhEnable:
    609       case EBhRequire:
    610       case EBhWarn:
    611           return true;
    612       default:
    613           break;
    614       }
    615       return false;
    616 }
    617 // See if any of the extensions are set to enable, require, or warn.
    618 bool TParseVersions::extensionsTurnedOn(int numExtensions, const char* const extensions[])
    619 {
    620     for (int i = 0; i < numExtensions; ++i) {
    621         if (extensionTurnedOn(extensions[i])) return true;
    622     }
    623     return false;
    624 }
    625 
    626 //
    627 // Change the current state of an extension's behavior.
    628 //
    629 void TParseVersions::updateExtensionBehavior(int line, const char* extension, const char* behaviorString)
    630 {
    631     // Translate from text string of extension's behavior to an enum.
    632     TExtensionBehavior behavior = EBhDisable;
    633     if (! strcmp("require", behaviorString))
    634         behavior = EBhRequire;
    635     else if (! strcmp("enable", behaviorString))
    636         behavior = EBhEnable;
    637     else if (! strcmp("disable", behaviorString))
    638         behavior = EBhDisable;
    639     else if (! strcmp("warn", behaviorString))
    640         behavior = EBhWarn;
    641     else {
    642         error(getCurrentLoc(), "behavior not supported:", "#extension", behaviorString);
    643         return;
    644     }
    645 
    646     // update the requested extension
    647     updateExtensionBehavior(extension, behavior);
    648 
    649     // see if need to propagate to implicitly modified things
    650     if (strcmp(extension, "GL_ANDROID_extension_pack_es31a") == 0) {
    651         // to everything in AEP
    652         updateExtensionBehavior(line, "GL_KHR_blend_equation_advanced", behaviorString);
    653         updateExtensionBehavior(line, "GL_OES_sample_variables", behaviorString);
    654         updateExtensionBehavior(line, "GL_OES_shader_image_atomic", behaviorString);
    655         updateExtensionBehavior(line, "GL_OES_shader_multisample_interpolation", behaviorString);
    656         updateExtensionBehavior(line, "GL_OES_texture_storage_multisample_2d_array", behaviorString);
    657         updateExtensionBehavior(line, "GL_EXT_geometry_shader", behaviorString);
    658         updateExtensionBehavior(line, "GL_EXT_gpu_shader5", behaviorString);
    659         updateExtensionBehavior(line, "GL_EXT_primitive_bounding_box", behaviorString);
    660         updateExtensionBehavior(line, "GL_EXT_shader_io_blocks", behaviorString);
    661         updateExtensionBehavior(line, "GL_EXT_tessellation_shader", behaviorString);
    662         updateExtensionBehavior(line, "GL_EXT_texture_buffer", behaviorString);
    663         updateExtensionBehavior(line, "GL_EXT_texture_cube_map_array", behaviorString);
    664     }
    665     // geometry to io_blocks
    666     else if (strcmp(extension, "GL_EXT_geometry_shader") == 0)
    667         updateExtensionBehavior(line, "GL_EXT_shader_io_blocks", behaviorString);
    668     else if (strcmp(extension, "GL_OES_geometry_shader") == 0)
    669         updateExtensionBehavior(line, "GL_OES_shader_io_blocks", behaviorString);
    670     // tessellation to io_blocks
    671     else if (strcmp(extension, "GL_EXT_tessellation_shader") == 0)
    672         updateExtensionBehavior(line, "GL_EXT_shader_io_blocks", behaviorString);
    673     else if (strcmp(extension, "GL_OES_tessellation_shader") == 0)
    674         updateExtensionBehavior(line, "GL_OES_shader_io_blocks", behaviorString);
    675     else if (strcmp(extension, "GL_GOOGLE_include_directive") == 0)
    676         updateExtensionBehavior(line, "GL_GOOGLE_cpp_style_line_directive", behaviorString);
    677 }
    678 
    679 void TParseVersions::updateExtensionBehavior(const char* extension, TExtensionBehavior behavior)
    680 {
    681     // Update the current behavior
    682     if (strcmp(extension, "all") == 0) {
    683         // special case for the 'all' extension; apply it to every extension present
    684         if (behavior == EBhRequire || behavior == EBhEnable) {
    685             error(getCurrentLoc(), "extension 'all' cannot have 'require' or 'enable' behavior", "#extension", "");
    686             return;
    687         } else {
    688             for (auto iter = extensionBehavior.begin(); iter != extensionBehavior.end(); ++iter)
    689                 iter->second = behavior;
    690         }
    691     } else {
    692         // Do the update for this single extension
    693         auto iter = extensionBehavior.find(TString(extension));
    694         if (iter == extensionBehavior.end()) {
    695             switch (behavior) {
    696             case EBhRequire:
    697                 error(getCurrentLoc(), "extension not supported:", "#extension", extension);
    698                 break;
    699             case EBhEnable:
    700             case EBhWarn:
    701             case EBhDisable:
    702                 warn(getCurrentLoc(), "extension not supported:", "#extension", extension);
    703                 break;
    704             default:
    705                 assert(0 && "unexpected behavior");
    706             }
    707 
    708             return;
    709         } else {
    710             if (iter->second == EBhDisablePartial)
    711                 warn(getCurrentLoc(), "extension is only partially supported:", "#extension", extension);
    712             if (behavior == EBhEnable || behavior == EBhRequire)
    713                 intermediate.addRequestedExtension(extension);
    714             iter->second = behavior;
    715         }
    716     }
    717 }
    718 
    719 // Call for any operation needing full GLSL integer data-type support.
    720 void TParseVersions::fullIntegerCheck(const TSourceLoc& loc, const char* op)
    721 {
    722     profileRequires(loc, ENoProfile, 130, nullptr, op);
    723     profileRequires(loc, EEsProfile, 300, nullptr, op);
    724 }
    725 
    726 // Call for any operation needing GLSL double data-type support.
    727 void TParseVersions::doubleCheck(const TSourceLoc& loc, const char* op)
    728 {
    729     requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
    730     profileRequires(loc, ECoreProfile, 400, nullptr, op);
    731     profileRequires(loc, ECompatibilityProfile, 400, nullptr, op);
    732 }
    733 
    734 #ifdef AMD_EXTENSIONS
    735 // Call for any operation needing GLSL 16-bit integer data-type support.
    736 void TParseVersions::int16Check(const TSourceLoc& loc, const char* op, bool builtIn)
    737 {
    738     if (! builtIn) {
    739         requireExtensions(loc, 1, &E_GL_AMD_gpu_shader_int16, "shader int16");
    740         requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
    741         profileRequires(loc, ECoreProfile, 450, nullptr, op);
    742         profileRequires(loc, ECompatibilityProfile, 450, nullptr, op);
    743     }
    744 }
    745 
    746 // Call for any operation needing GLSL float16 data-type support.
    747 void TParseVersions::float16Check(const TSourceLoc& loc, const char* op, bool builtIn)
    748 {
    749     if (! builtIn) {
    750         requireExtensions(loc, 1, &E_GL_AMD_gpu_shader_half_float, "shader half float");
    751         requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
    752         profileRequires(loc, ECoreProfile, 450, nullptr, op);
    753         profileRequires(loc, ECompatibilityProfile, 450, nullptr, op);
    754     }
    755 }
    756 #endif
    757 
    758 // Call for any operation needing GLSL 64-bit integer data-type support.
    759 void TParseVersions::int64Check(const TSourceLoc& loc, const char* op, bool builtIn)
    760 {
    761     if (! builtIn) {
    762         requireExtensions(loc, 1, &E_GL_ARB_gpu_shader_int64, "shader int64");
    763         requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
    764         profileRequires(loc, ECoreProfile, 450, nullptr, op);
    765         profileRequires(loc, ECompatibilityProfile, 450, nullptr, op);
    766     }
    767 }
    768 
    769 // Call for any operation removed because SPIR-V is in use.
    770 void TParseVersions::spvRemoved(const TSourceLoc& loc, const char* op)
    771 {
    772     if (spvVersion.spv != 0)
    773         error(loc, "not allowed when generating SPIR-V", op, "");
    774 }
    775 
    776 // Call for any operation removed because Vulkan SPIR-V is being generated.
    777 void TParseVersions::vulkanRemoved(const TSourceLoc& loc, const char* op)
    778 {
    779     if (spvVersion.vulkan >= 100)
    780         error(loc, "not allowed when using GLSL for Vulkan", op, "");
    781 }
    782 
    783 // Call for any operation that requires Vulkan.
    784 void TParseVersions::requireVulkan(const TSourceLoc& loc, const char* op)
    785 {
    786     if (spvVersion.vulkan == 0)
    787         error(loc, "only allowed when using GLSL for Vulkan", op, "");
    788 }
    789 
    790 // Call for any operation that requires SPIR-V.
    791 void TParseVersions::requireSpv(const TSourceLoc& loc, const char* op)
    792 {
    793     if (spvVersion.spv == 0)
    794         error(loc, "only allowed when generating SPIR-V", op, "");
    795 }
    796 
    797 } // end namespace glslang
    798