1 /* 2 * Copyright 2016 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SKSL_UTIL 9 #define SKSL_UTIL 10 11 #include <cstdarg> 12 #include <memory> 13 #include "stdlib.h" 14 #include "string.h" 15 #include "src/sksl/SkSLDefines.h" 16 #include "src/sksl/SkSLLexer.h" 17 18 #ifndef SKSL_STANDALONE 19 #include "include/core/SkTypes.h" 20 #include "include/private/GrTypesPriv.h" 21 #if SK_SUPPORT_GPU 22 #include "include/gpu/GrContextOptions.h" 23 #include "src/gpu/GrShaderCaps.h" 24 #endif // SK_SUPPORT_GPU 25 #endif // SKSL_STANDALONE 26 27 class GrShaderCaps; 28 29 namespace SkSL { 30 31 class Context; 32 class OutputStream; 33 class StringStream; 34 class Type; 35 36 #if defined(SKSL_STANDALONE) || !SK_SUPPORT_GPU 37 38 // we're being compiled standalone, so we don't have access to caps... 39 enum GrGLSLGeneration { 40 k110_GrGLSLGeneration, 41 k130_GrGLSLGeneration, 42 k140_GrGLSLGeneration, 43 k150_GrGLSLGeneration, 44 k330_GrGLSLGeneration, 45 k400_GrGLSLGeneration, 46 k420_GrGLSLGeneration, 47 k310es_GrGLSLGeneration, 48 k320es_GrGLSLGeneration, 49 }; 50 51 class StandaloneShaderCaps { 52 public: 53 GrGLSLGeneration fGLSLGeneration = k400_GrGLSLGeneration; generation()54 GrGLSLGeneration generation() const { 55 return fGLSLGeneration; 56 } 57 58 bool fAtan2ImplementedAsAtanYOverX = false; atan2ImplementedAsAtanYOverX()59 bool atan2ImplementedAsAtanYOverX() const { 60 return fAtan2ImplementedAsAtanYOverX; 61 } 62 63 bool fCanUseMinAndAbsTogether = true; canUseMinAndAbsTogether()64 bool canUseMinAndAbsTogether() const { 65 return fCanUseMinAndAbsTogether; 66 } 67 68 bool fMustForceNegatedAtanParamToFloat = false; mustForceNegatedAtanParamToFloat()69 bool mustForceNegatedAtanParamToFloat() const { 70 return fMustForceNegatedAtanParamToFloat; 71 } 72 73 bool fGeometryShaderSupport = true; geometryShaderSupport()74 bool geometryShaderSupport() const { 75 return fGeometryShaderSupport; 76 } 77 78 bool fShaderDerivativeSupport = true; shaderDerivativeSupport()79 bool shaderDerivativeSupport() const { 80 return fShaderDerivativeSupport; 81 } 82 83 bool fUsesPrecisionModifiers = false; usesPrecisionModifiers()84 bool usesPrecisionModifiers() const { 85 return fUsesPrecisionModifiers; 86 } 87 mustDeclareFragmentShaderOutput()88 bool mustDeclareFragmentShaderOutput() const { 89 return fGLSLGeneration > k110_GrGLSLGeneration; 90 } 91 92 bool fFBFetchSupport = true; fbFetchSupport()93 bool fbFetchSupport() const { 94 return fFBFetchSupport; 95 } 96 97 bool fFBFetchNeedsCustomOutput = false; fbFetchNeedsCustomOutput()98 bool fbFetchNeedsCustomOutput() const { 99 return fFBFetchNeedsCustomOutput; 100 } 101 102 bool fFlatInterpolationSupport = true; flatInterpolationSupport()103 bool flatInterpolationSupport() const { 104 return fFlatInterpolationSupport; 105 } 106 107 bool fNoperspectiveInterpolationSupport = true; noperspectiveInterpolationSupport()108 bool noperspectiveInterpolationSupport() const { 109 return fNoperspectiveInterpolationSupport; 110 } 111 112 bool fMultisampleInterpolationSupport = true; multisampleInterpolationSupport()113 bool multisampleInterpolationSupport() const { 114 return fMultisampleInterpolationSupport; 115 } 116 117 bool fSampleMaskSupport = true; sampleMaskSupport()118 bool sampleMaskSupport() const { 119 return fSampleMaskSupport; 120 } 121 122 bool fExternalTextureSupport = true; externalTextureSupport()123 bool externalTextureSupport() const { 124 return fExternalTextureSupport; 125 } 126 127 bool fMustDoOpBetweenFloorAndAbs = false; mustDoOpBetweenFloorAndAbs()128 bool mustDoOpBetweenFloorAndAbs() const { 129 return fMustDoOpBetweenFloorAndAbs; 130 } 131 132 bool fMustGuardDivisionEvenAfterExplicitZeroCheck = false; mustGuardDivisionEvenAfterExplicitZeroCheck()133 bool mustGuardDivisionEvenAfterExplicitZeroCheck() const { 134 return fMustGuardDivisionEvenAfterExplicitZeroCheck; 135 } 136 137 bool fInBlendModesFailRandomlyForAllZeroVec = false; inBlendModesFailRandomlyForAllZeroVec()138 bool inBlendModesFailRandomlyForAllZeroVec() const { 139 return fInBlendModesFailRandomlyForAllZeroVec; 140 } 141 142 bool fMustEnableAdvBlendEqs = false; mustEnableAdvBlendEqs()143 bool mustEnableAdvBlendEqs() const { 144 return fMustEnableAdvBlendEqs; 145 } 146 147 bool fMustEnableSpecificAdvBlendEqs = false; mustEnableSpecificAdvBlendEqs()148 bool mustEnableSpecificAdvBlendEqs() const { 149 return fMustEnableSpecificAdvBlendEqs; 150 } 151 152 bool fCanUseAnyFunctionInShader = true; canUseAnyFunctionInShader()153 bool canUseAnyFunctionInShader() const { 154 return fCanUseAnyFunctionInShader; 155 } 156 157 bool fNoDefaultPrecisionForExternalSamplers = false; noDefaultPrecisionForExternalSamplers()158 bool noDefaultPrecisionForExternalSamplers() const { 159 return fNoDefaultPrecisionForExternalSamplers; 160 } 161 162 bool fFloatIs32Bits = true; floatIs32Bits()163 bool floatIs32Bits() const { 164 return fFloatIs32Bits; 165 } 166 167 bool fIntegerSupport = false; integerSupport()168 bool integerSupport() const { 169 return fIntegerSupport; 170 } 171 172 bool fBuiltinFMASupport = false; builtinFMASupport()173 bool builtinFMASupport() const { 174 return fBuiltinFMASupport; 175 } 176 177 bool fBuiltinDeterminantSupport = false; builtinDeterminantSupport()178 bool builtinDeterminantSupport() const { 179 return fBuiltinDeterminantSupport; 180 } 181 182 bool fCanUseDoLoops = false; canUseDoLoops()183 bool canUseDoLoops() const { 184 // we define this to false in standalone so we don't use do loops while inlining in FP files 185 // (which would then, being baked in, end up being used even in contexts where do loops are 186 // not allowed) 187 return fCanUseDoLoops; 188 } 189 190 const char* fShaderDerivativeExtensionString = nullptr; shaderDerivativeExtensionString()191 const char* shaderDerivativeExtensionString() const { 192 return fShaderDerivativeExtensionString; 193 } 194 195 const char* fFragCoordConventionsExtensionString = nullptr; fragCoordConventionsExtensionString()196 const char* fragCoordConventionsExtensionString() const { 197 return fFragCoordConventionsExtensionString; 198 } 199 200 const char* fGeometryShaderExtensionString = nullptr; geometryShaderExtensionString()201 const char* geometryShaderExtensionString() const { 202 return fGeometryShaderExtensionString; 203 } 204 205 const char* fGSInvocationsExtensionString = nullptr; gsInvocationsExtensionString()206 const char* gsInvocationsExtensionString() const { 207 return fGSInvocationsExtensionString; 208 } 209 210 const char* fExternalTextureExtensionString = nullptr; externalTextureExtensionString()211 const char* externalTextureExtensionString() const { 212 return fExternalTextureExtensionString; 213 } 214 215 const char* fSecondExternalTextureExtensionString = nullptr; secondExternalTextureExtensionString()216 const char* secondExternalTextureExtensionString() const { 217 return fSecondExternalTextureExtensionString; 218 } 219 220 const char* fVersionDeclString = ""; versionDeclString()221 const char* versionDeclString() const { 222 return fVersionDeclString; 223 } 224 225 bool fGSInvocationsSupport = true; gsInvocationsSupport()226 bool gsInvocationsSupport() const { 227 return fGSInvocationsSupport; 228 } 229 230 bool fCanUseFractForNegativeValues = true; canUseFractForNegativeValues()231 bool canUseFractForNegativeValues() const { 232 return fCanUseFractForNegativeValues; 233 } 234 235 bool fCanUseFragCoord = true; canUseFragCoord()236 bool canUseFragCoord() const { 237 return fCanUseFragCoord; 238 } 239 240 bool fIncompleteShortIntPrecision = false; incompleteShortIntPrecision()241 bool incompleteShortIntPrecision() const { 242 return fIncompleteShortIntPrecision; 243 } 244 245 bool fAddAndTrueToLoopCondition = false; addAndTrueToLoopCondition()246 bool addAndTrueToLoopCondition() const { 247 return fAddAndTrueToLoopCondition; 248 } 249 250 bool fUnfoldShortCircuitAsTernary = false; unfoldShortCircuitAsTernary()251 bool unfoldShortCircuitAsTernary() const { 252 return fUnfoldShortCircuitAsTernary; 253 } 254 255 bool fEmulateAbsIntFunction = false; emulateAbsIntFunction()256 bool emulateAbsIntFunction() const { 257 return fEmulateAbsIntFunction; 258 } 259 260 bool fRewriteDoWhileLoops = false; rewriteDoWhileLoops()261 bool rewriteDoWhileLoops() const { 262 return fRewriteDoWhileLoops; 263 } 264 265 bool fRemovePowWithConstantExponent = false; removePowWithConstantExponent()266 bool removePowWithConstantExponent() const { 267 return fRemovePowWithConstantExponent; 268 } 269 270 const char* fFBFetchColorName = nullptr; fbFetchColorName()271 const char* fbFetchColorName() const { 272 return fFBFetchColorName; 273 } 274 }; 275 276 using ShaderCapsClass = StandaloneShaderCaps; 277 using ShaderCapsPointer = std::shared_ptr<StandaloneShaderCaps>; 278 extern StandaloneShaderCaps standaloneCaps; 279 280 #else 281 282 using ShaderCapsClass = GrShaderCaps; 283 using ShaderCapsPointer = sk_sp<GrShaderCaps>; 284 285 #endif // defined(SKSL_STANDALONE) || !SK_SUPPORT_GPU 286 287 // Various sets of caps for use in tests 288 class ShaderCapsFactory { 289 public: Default()290 static ShaderCapsPointer Default() { 291 ShaderCapsPointer result = MakeShaderCaps(); 292 result->fVersionDeclString = "#version 400"; 293 result->fShaderDerivativeSupport = true; 294 result->fBuiltinDeterminantSupport = true; 295 result->fCanUseDoLoops = true; 296 return result; 297 } 298 Standalone()299 static ShaderCapsPointer Standalone() { 300 return MakeShaderCaps(); 301 } 302 AddAndTrueToLoopCondition()303 static ShaderCapsPointer AddAndTrueToLoopCondition() { 304 ShaderCapsPointer result = MakeShaderCaps(); 305 result->fVersionDeclString = "#version 400"; 306 result->fAddAndTrueToLoopCondition = true; 307 return result; 308 } 309 BlendModesFailRandomlyForAllZeroVec()310 static ShaderCapsPointer BlendModesFailRandomlyForAllZeroVec() { 311 ShaderCapsPointer result = MakeShaderCaps(); 312 result->fInBlendModesFailRandomlyForAllZeroVec = true; 313 return result; 314 } 315 CannotUseFractForNegativeValues()316 static ShaderCapsPointer CannotUseFractForNegativeValues() { 317 ShaderCapsPointer result = MakeShaderCaps(); 318 result->fVersionDeclString = "#version 400"; 319 result->fCanUseFractForNegativeValues = false; 320 return result; 321 } 322 CannotUseFragCoord()323 static ShaderCapsPointer CannotUseFragCoord() { 324 ShaderCapsPointer result = MakeShaderCaps(); 325 result->fVersionDeclString = "#version 400"; 326 result->fCanUseFragCoord = false; 327 return result; 328 } 329 CannotUseMinAndAbsTogether()330 static ShaderCapsPointer CannotUseMinAndAbsTogether() { 331 ShaderCapsPointer result = MakeShaderCaps(); 332 result->fVersionDeclString = "#version 400"; 333 result->fCanUseMinAndAbsTogether = false; 334 return result; 335 } 336 EmulateAbsIntFunction()337 static ShaderCapsPointer EmulateAbsIntFunction() { 338 ShaderCapsPointer result = MakeShaderCaps(); 339 result->fVersionDeclString = "#version 400"; 340 result->fEmulateAbsIntFunction = true; 341 return result; 342 } 343 FragCoordsNew()344 static ShaderCapsPointer FragCoordsNew() { 345 ShaderCapsPointer result = MakeShaderCaps(); 346 result->fVersionDeclString = "#version 400"; 347 result->fFragCoordConventionsExtensionString = "GL_ARB_fragment_coord_conventions"; 348 return result; 349 } FragCoordsOld()350 static ShaderCapsPointer FragCoordsOld() { 351 ShaderCapsPointer result = MakeShaderCaps(); 352 result->fVersionDeclString = "#version 110"; 353 result->fGLSLGeneration = GrGLSLGeneration::k110_GrGLSLGeneration; 354 result->fFragCoordConventionsExtensionString = "GL_ARB_fragment_coord_conventions"; 355 return result; 356 } 357 GeometryShaderExtensionString()358 static ShaderCapsPointer GeometryShaderExtensionString() { 359 ShaderCapsPointer result = MakeShaderCaps(); 360 result->fVersionDeclString = "#version 310es"; 361 result->fGeometryShaderSupport = true; 362 result->fGeometryShaderExtensionString = "GL_EXT_geometry_shader"; 363 result->fGSInvocationsSupport = true; 364 return result; 365 } 366 GeometryShaderSupport()367 static ShaderCapsPointer GeometryShaderSupport() { 368 ShaderCapsPointer result = MakeShaderCaps(); 369 result->fVersionDeclString = "#version 400"; 370 result->fGeometryShaderSupport = true; 371 result->fGSInvocationsSupport = true; 372 return result; 373 } 374 GSInvocationsExtensionString()375 static ShaderCapsPointer GSInvocationsExtensionString() { 376 ShaderCapsPointer result = MakeShaderCaps(); 377 result->fVersionDeclString = "#version 400"; 378 result->fGeometryShaderSupport = true; 379 result->fGSInvocationsSupport = true; 380 result->fGSInvocationsExtensionString = "GL_ARB_gpu_shader5"; 381 return result; 382 } 383 IncompleteShortIntPrecision()384 static ShaderCapsPointer IncompleteShortIntPrecision() { 385 ShaderCapsPointer result = MakeShaderCaps(); 386 result->fVersionDeclString = "#version 310es"; 387 result->fUsesPrecisionModifiers = true; 388 result->fIncompleteShortIntPrecision = true; 389 return result; 390 } 391 MustForceNegatedAtanParamToFloat()392 static ShaderCapsPointer MustForceNegatedAtanParamToFloat() { 393 ShaderCapsPointer result = MakeShaderCaps(); 394 result->fVersionDeclString = "#version 400"; 395 result->fMustForceNegatedAtanParamToFloat = true; 396 return result; 397 } 398 MustGuardDivisionEvenAfterExplicitZeroCheck()399 static ShaderCapsPointer MustGuardDivisionEvenAfterExplicitZeroCheck() { 400 ShaderCapsPointer result = MakeShaderCaps(); 401 result->fMustGuardDivisionEvenAfterExplicitZeroCheck = true; 402 return result; 403 } 404 NoGSInvocationsSupport()405 static ShaderCapsPointer NoGSInvocationsSupport() { 406 ShaderCapsPointer result = MakeShaderCaps(); 407 result->fVersionDeclString = "#version 400"; 408 result->fGeometryShaderSupport = true; 409 result->fGSInvocationsSupport = false; 410 return result; 411 } 412 RemovePowWithConstantExponent()413 static ShaderCapsPointer RemovePowWithConstantExponent() { 414 ShaderCapsPointer result = MakeShaderCaps(); 415 result->fVersionDeclString = "#version 400"; 416 result->fRemovePowWithConstantExponent = true; 417 return result; 418 } 419 RewriteDoWhileLoops()420 static ShaderCapsPointer RewriteDoWhileLoops() { 421 ShaderCapsPointer result = MakeShaderCaps(); 422 result->fVersionDeclString = "#version 400"; 423 result->fRewriteDoWhileLoops = true; 424 return result; 425 } 426 SampleMaskSupport()427 static ShaderCapsPointer SampleMaskSupport() { 428 ShaderCapsPointer result = Default(); 429 result->fSampleMaskSupport = true; 430 return result; 431 } 432 ShaderDerivativeExtensionString()433 static ShaderCapsPointer ShaderDerivativeExtensionString() { 434 ShaderCapsPointer result = MakeShaderCaps(); 435 result->fVersionDeclString = "#version 400"; 436 result->fShaderDerivativeSupport = true; 437 result->fShaderDerivativeExtensionString = "GL_OES_standard_derivatives"; 438 result->fUsesPrecisionModifiers = true; 439 return result; 440 } 441 UnfoldShortCircuitAsTernary()442 static ShaderCapsPointer UnfoldShortCircuitAsTernary() { 443 ShaderCapsPointer result = MakeShaderCaps(); 444 result->fVersionDeclString = "#version 400"; 445 result->fUnfoldShortCircuitAsTernary = true; 446 return result; 447 } 448 UsesPrecisionModifiers()449 static ShaderCapsPointer UsesPrecisionModifiers() { 450 ShaderCapsPointer result = MakeShaderCaps(); 451 result->fVersionDeclString = "#version 400"; 452 result->fUsesPrecisionModifiers = true; 453 return result; 454 } 455 Version110()456 static ShaderCapsPointer Version110() { 457 ShaderCapsPointer result = MakeShaderCaps(); 458 result->fVersionDeclString = "#version 110"; 459 result->fGLSLGeneration = GrGLSLGeneration::k110_GrGLSLGeneration; 460 return result; 461 } 462 Version450Core()463 static ShaderCapsPointer Version450Core() { 464 ShaderCapsPointer result = MakeShaderCaps(); 465 result->fVersionDeclString = "#version 450 core"; 466 return result; 467 } 468 469 private: 470 static ShaderCapsPointer MakeShaderCaps(); 471 }; 472 473 #if !defined(SKSL_STANDALONE) 474 bool type_to_grsltype(const Context& context, const Type& type, GrSLType* outType); 475 #endif 476 477 void write_stringstream(const StringStream& d, OutputStream& out); 478 479 NORETURN void sksl_abort(); 480 481 } // namespace SkSL 482 483 #endif // SKSL_UTIL 484