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