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