DirectiveHandler.cpp (10577B)
1 // 2 // Copyright 2012 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 #include "compiler/translator/DirectiveHandler.h" 8 9 #include <sstream> 10 11 #include "angle_gl.h" 12 #include "common/debug.h" 13 #include "compiler/translator/Common.h" 14 #include "compiler/translator/Diagnostics.h" 15 16 namespace sh 17 { 18 19 static TBehavior getBehavior(const std::string &str) 20 { 21 const char kRequire[] = "require"; 22 const char kEnable[] = "enable"; 23 const char kDisable[] = "disable"; 24 const char kWarn[] = "warn"; 25 26 if (str == kRequire) 27 return EBhRequire; 28 else if (str == kEnable) 29 return EBhEnable; 30 else if (str == kDisable) 31 return EBhDisable; 32 else if (str == kWarn) 33 return EBhWarn; 34 return EBhUndefined; 35 } 36 37 TDirectiveHandler::TDirectiveHandler(TExtensionBehavior &extBehavior, 38 TDiagnostics &diagnostics, 39 int &shaderVersion, 40 sh::GLenum shaderType) 41 : mExtensionBehavior(extBehavior), 42 mDiagnostics(diagnostics), 43 mShaderVersion(shaderVersion), 44 mShaderType(shaderType) 45 {} 46 47 TDirectiveHandler::~TDirectiveHandler() {} 48 49 void TDirectiveHandler::handleError(const angle::pp::SourceLocation &loc, const std::string &msg) 50 { 51 mDiagnostics.error(loc, msg.c_str(), ""); 52 } 53 54 void TDirectiveHandler::handlePragma(const angle::pp::SourceLocation &loc, 55 const std::string &name, 56 const std::string &value, 57 bool stdgl) 58 { 59 if (stdgl) 60 { 61 const char kInvariant[] = "invariant"; 62 const char kAll[] = "all"; 63 64 if (name == kInvariant && value == kAll) 65 { 66 if (mShaderVersion == 300 && mShaderType == GL_FRAGMENT_SHADER) 67 { 68 // ESSL 3.00.4 section 4.6.1 69 mDiagnostics.error( 70 loc, "#pragma STDGL invariant(all) can not be used in fragment shader", 71 name.c_str()); 72 } 73 mPragma.stdgl.invariantAll = true; 74 } 75 // The STDGL pragma is used to reserve pragmas for use by future 76 // revisions of GLSL. Do not generate an error on unexpected 77 // name and value. 78 return; 79 } 80 else 81 { 82 const char kOptimize[] = "optimize"; 83 const char kDebug[] = "debug"; 84 const char kOn[] = "on"; 85 const char kOff[] = "off"; 86 87 bool invalidValue = false; 88 if (name == kOptimize) 89 { 90 if (value == kOn) 91 mPragma.optimize = true; 92 else if (value == kOff) 93 mPragma.optimize = false; 94 else 95 invalidValue = true; 96 } 97 else if (name == kDebug) 98 { 99 if (value == kOn) 100 mPragma.debug = true; 101 else if (value == kOff) 102 mPragma.debug = false; 103 else 104 invalidValue = true; 105 } 106 else 107 { 108 mDiagnostics.report(angle::pp::Diagnostics::PP_UNRECOGNIZED_PRAGMA, loc, name); 109 return; 110 } 111 112 if (invalidValue) 113 { 114 mDiagnostics.error(loc, "invalid pragma value - 'on' or 'off' expected", value.c_str()); 115 } 116 } 117 } 118 119 void TDirectiveHandler::handleExtension(const angle::pp::SourceLocation &loc, 120 const std::string &name, 121 const std::string &behavior) 122 { 123 const char kExtAll[] = "all"; 124 125 TBehavior behaviorVal = getBehavior(behavior); 126 if (behaviorVal == EBhUndefined) 127 { 128 mDiagnostics.error(loc, "behavior invalid", name.c_str()); 129 return; 130 } 131 132 if (name == kExtAll) 133 { 134 if (behaviorVal == EBhRequire) 135 { 136 mDiagnostics.error(loc, "extension cannot have 'require' behavior", name.c_str()); 137 } 138 else if (behaviorVal == EBhEnable) 139 { 140 mDiagnostics.error(loc, "extension cannot have 'enable' behavior", name.c_str()); 141 } 142 else 143 { 144 for (TExtensionBehavior::iterator iter = mExtensionBehavior.begin(); 145 iter != mExtensionBehavior.end(); ++iter) 146 iter->second = behaviorVal; 147 } 148 return; 149 } 150 151 TExtensionBehavior::iterator iter = mExtensionBehavior.find(GetExtensionByName(name.c_str())); 152 if (iter != mExtensionBehavior.end()) 153 { 154 iter->second = behaviorVal; 155 // OVR_multiview is implicitly enabled when OVR_multiview2 is enabled 156 if (name == "GL_OVR_multiview2") 157 { 158 constexpr char kMultiviewExtName[] = "GL_OVR_multiview"; 159 iter = mExtensionBehavior.find(GetExtensionByName(kMultiviewExtName)); 160 if (iter != mExtensionBehavior.end()) 161 { 162 iter->second = behaviorVal; 163 } 164 } 165 // All the extensions listed in the spec here: 166 // https://www.khronos.org/registry/OpenGL/extensions/ANDROID/ANDROID_extension_pack_es31a.txt 167 // are implicitly enabled when GL_ANDROID_extension_pack_es31a is enabled 168 if (name == "GL_ANDROID_extension_pack_es31a") 169 { 170 constexpr char kGeometryShaderExtName[] = "GL_EXT_geometry_shader"; 171 constexpr char kTessellationShaderExtName[] = "GL_EXT_tessellation_shader"; 172 constexpr char kGpuShader5ExtName[] = "GL_EXT_gpu_shader5"; 173 constexpr char kTextureBufferExtName[] = "GL_EXT_texture_buffer"; 174 constexpr char kTextureCubeMapArrayExtName[] = "GL_EXT_texture_cube_map_array"; 175 constexpr char kSampleVariablesExtName[] = "GL_OES_sample_variables"; 176 constexpr char kShaderMultisampleInterpolationExtName[] = 177 "GL_OES_shader_multisample_interpolation"; 178 constexpr char kShaderImageAtomicExtName[] = "GL_OES_shader_image_atomic"; 179 constexpr char kTextureStorageMultisample2dArrayExtName[] = 180 "GL_OES_texture_storage_multisample_2d_array"; 181 iter = mExtensionBehavior.find(GetExtensionByName(kGeometryShaderExtName)); 182 if (iter != mExtensionBehavior.end()) 183 { 184 iter->second = behaviorVal; 185 } 186 187 iter = mExtensionBehavior.find(GetExtensionByName(kTessellationShaderExtName)); 188 if (iter != mExtensionBehavior.end()) 189 { 190 iter->second = behaviorVal; 191 } 192 193 iter = mExtensionBehavior.find(GetExtensionByName(kGpuShader5ExtName)); 194 if (iter != mExtensionBehavior.end()) 195 { 196 iter->second = behaviorVal; 197 } 198 199 iter = mExtensionBehavior.find(GetExtensionByName(kTextureBufferExtName)); 200 if (iter != mExtensionBehavior.end()) 201 { 202 iter->second = behaviorVal; 203 } 204 205 iter = mExtensionBehavior.find(GetExtensionByName(kTextureCubeMapArrayExtName)); 206 if (iter != mExtensionBehavior.end()) 207 { 208 iter->second = behaviorVal; 209 } 210 211 iter = mExtensionBehavior.find(GetExtensionByName(kSampleVariablesExtName)); 212 if (iter != mExtensionBehavior.end()) 213 { 214 iter->second = behaviorVal; 215 } 216 217 iter = 218 mExtensionBehavior.find(GetExtensionByName(kShaderMultisampleInterpolationExtName)); 219 if (iter != mExtensionBehavior.end()) 220 { 221 iter->second = behaviorVal; 222 } 223 224 iter = mExtensionBehavior.find(GetExtensionByName(kShaderImageAtomicExtName)); 225 if (iter != mExtensionBehavior.end()) 226 { 227 iter->second = behaviorVal; 228 } 229 230 iter = mExtensionBehavior.find( 231 GetExtensionByName(kTextureStorageMultisample2dArrayExtName)); 232 if (iter != mExtensionBehavior.end()) 233 { 234 iter->second = behaviorVal; 235 } 236 } 237 // EXT_shader_io_blocks is implicitly enabled when EXT_geometry_shader or 238 // EXT_tessellation_shader is enabled. 239 if (name == "GL_EXT_geometry_shader" || name == "GL_EXT_tessellation_shader") 240 { 241 constexpr char kIOBlocksExtName[] = "GL_EXT_shader_io_blocks"; 242 iter = mExtensionBehavior.find(GetExtensionByName(kIOBlocksExtName)); 243 if (iter != mExtensionBehavior.end()) 244 { 245 iter->second = behaviorVal; 246 } 247 } 248 // GL_APPLE_clip_distance is implicitly enabled when GL_EXT_clip_cull_distance is enabled 249 else if (name == "GL_EXT_clip_cull_distance") 250 { 251 // This extension only can be enabled on greater than ESSL 300 252 if (mShaderVersion < 300) 253 { 254 mDiagnostics.error(loc, "extension can be enabled on greater than ESSL 300", 255 name.c_str()); 256 return; 257 } 258 259 constexpr char kAPPLEClipDistanceEXTName[] = "GL_APPLE_clip_distance"; 260 iter = mExtensionBehavior.find(GetExtensionByName(kAPPLEClipDistanceEXTName)); 261 if (iter != mExtensionBehavior.end()) 262 { 263 iter->second = behaviorVal; 264 } 265 } 266 return; 267 } 268 269 switch (behaviorVal) 270 { 271 case EBhRequire: 272 mDiagnostics.error(loc, "extension is not supported", name.c_str()); 273 break; 274 case EBhEnable: 275 case EBhWarn: 276 case EBhDisable: 277 mDiagnostics.warning(loc, "extension is not supported", name.c_str()); 278 break; 279 default: 280 UNREACHABLE(); 281 break; 282 } 283 } 284 285 void TDirectiveHandler::handleVersion(const angle::pp::SourceLocation &loc, 286 int version, 287 ShShaderSpec spec) 288 { 289 if (((version == 100 || version == 300 || version == 310 || version == 320) && 290 !IsDesktopGLSpec(spec)) || 291 IsDesktopGLSpec(spec)) 292 { 293 mShaderVersion = version; 294 } 295 else 296 { 297 std::stringstream stream = sh::InitializeStream<std::stringstream>(); 298 stream << version; 299 std::string str = stream.str(); 300 mDiagnostics.error(loc, "client/version number not supported", str.c_str()); 301 } 302 } 303 304 } // namespace sh