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 #include "src/sksl/SkSLLexer.h" 17 18 #ifndef SKSL_STANDALONE 19 #include "include/core/SkTypes.h" 20 #if SK_SUPPORT_GPU 21 #include "include/gpu/GrContextOptions.h" 22 #include "include/private/GrTypesPriv.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 fMustForceNegatedLdexpParamToMultiply = false; mustForceNegatedLdexpParamToMultiply()74 bool mustForceNegatedLdexpParamToMultiply() const { 75 return fMustForceNegatedLdexpParamToMultiply; 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 = false; 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 fMustEnableAdvBlendEqs = false; mustEnableAdvBlendEqs()138 bool mustEnableAdvBlendEqs() const { 139 return fMustEnableAdvBlendEqs; 140 } 141 142 bool fCanUseAnyFunctionInShader = true; canUseAnyFunctionInShader()143 bool canUseAnyFunctionInShader() const { 144 return fCanUseAnyFunctionInShader; 145 } 146 147 bool fNoDefaultPrecisionForExternalSamplers = false; noDefaultPrecisionForExternalSamplers()148 bool noDefaultPrecisionForExternalSamplers() const { 149 return fNoDefaultPrecisionForExternalSamplers; 150 } 151 152 bool fFloatIs32Bits = true; floatIs32Bits()153 bool floatIs32Bits() const { 154 return fFloatIs32Bits; 155 } 156 157 bool fIntegerSupport = false; integerSupport()158 bool integerSupport() const { 159 return fIntegerSupport; 160 } 161 162 bool fNonsquareMatrixSupport = false; nonsquareMatrixSupport()163 bool nonsquareMatrixSupport() const { 164 return fNonsquareMatrixSupport; 165 } 166 167 bool fInverseHyperbolicSupport = false; inverseHyperbolicSupport()168 bool inverseHyperbolicSupport() const { 169 return fInverseHyperbolicSupport; 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 bool fUseNodePools = true; useNodePools()191 bool useNodePools() const { 192 return fUseNodePools; 193 } 194 195 const char* fShaderDerivativeExtensionString = nullptr; shaderDerivativeExtensionString()196 const char* shaderDerivativeExtensionString() const { 197 return fShaderDerivativeExtensionString; 198 } 199 200 const char* fFragCoordConventionsExtensionString = nullptr; fragCoordConventionsExtensionString()201 const char* fragCoordConventionsExtensionString() const { 202 return fFragCoordConventionsExtensionString; 203 } 204 205 const char* fExternalTextureExtensionString = nullptr; externalTextureExtensionString()206 const char* externalTextureExtensionString() const { 207 return fExternalTextureExtensionString; 208 } 209 210 const char* fSecondExternalTextureExtensionString = nullptr; secondExternalTextureExtensionString()211 const char* secondExternalTextureExtensionString() const { 212 return fSecondExternalTextureExtensionString; 213 } 214 215 const char* fVersionDeclString = ""; versionDeclString()216 const char* versionDeclString() const { 217 return fVersionDeclString; 218 } 219 220 bool fCanUseFractForNegativeValues = true; canUseFractForNegativeValues()221 bool canUseFractForNegativeValues() const { 222 return fCanUseFractForNegativeValues; 223 } 224 225 bool fCanUseFragCoord = true; canUseFragCoord()226 bool canUseFragCoord() const { 227 return fCanUseFragCoord; 228 } 229 230 bool fIncompleteShortIntPrecision = false; incompleteShortIntPrecision()231 bool incompleteShortIntPrecision() const { 232 return fIncompleteShortIntPrecision; 233 } 234 235 bool fAddAndTrueToLoopCondition = false; addAndTrueToLoopCondition()236 bool addAndTrueToLoopCondition() const { 237 return fAddAndTrueToLoopCondition; 238 } 239 240 bool fUnfoldShortCircuitAsTernary = false; unfoldShortCircuitAsTernary()241 bool unfoldShortCircuitAsTernary() const { 242 return fUnfoldShortCircuitAsTernary; 243 } 244 245 bool fEmulateAbsIntFunction = false; emulateAbsIntFunction()246 bool emulateAbsIntFunction() const { 247 return fEmulateAbsIntFunction; 248 } 249 250 bool fRewriteDoWhileLoops = false; rewriteDoWhileLoops()251 bool rewriteDoWhileLoops() const { 252 return fRewriteDoWhileLoops; 253 } 254 255 bool fRewriteSwitchStatements = false; rewriteSwitchStatements()256 bool rewriteSwitchStatements() const { 257 return fRewriteSwitchStatements; 258 } 259 260 bool fRemovePowWithConstantExponent = false; removePowWithConstantExponent()261 bool removePowWithConstantExponent() const { 262 return fRemovePowWithConstantExponent; 263 } 264 265 const char* fFBFetchColorName = nullptr; fbFetchColorName()266 const char* fbFetchColorName() const { 267 return fFBFetchColorName; 268 } 269 270 bool fRewriteMatrixVectorMultiply = false; rewriteMatrixVectorMultiply()271 bool rewriteMatrixVectorMultiply() const { 272 return fRewriteMatrixVectorMultiply; 273 } 274 275 bool fRewriteMatrixComparisons = false; rewriteMatrixComparisons()276 bool rewriteMatrixComparisons() const { 277 return fRewriteMatrixComparisons; 278 } 279 }; 280 281 using ShaderCapsClass = StandaloneShaderCaps; 282 using ShaderCapsPointer = std::unique_ptr<StandaloneShaderCaps>; 283 284 #else 285 286 using ShaderCapsClass = GrShaderCaps; 287 using ShaderCapsPointer = std::unique_ptr<GrShaderCaps>; 288 289 #endif // defined(SKSL_STANDALONE) || !SK_SUPPORT_GPU 290 291 // Various sets of caps for use in tests 292 class ShaderCapsFactory { 293 public: Default()294 static ShaderCapsPointer Default() { 295 ShaderCapsPointer result = MakeShaderCaps(); 296 result->fVersionDeclString = "#version 400"; 297 result->fShaderDerivativeSupport = true; 298 result->fBuiltinDeterminantSupport = true; 299 result->fCanUseDoLoops = true; 300 return result; 301 } 302 Standalone()303 static ShaderCapsPointer Standalone() { 304 return MakeShaderCaps(); 305 } 306 AddAndTrueToLoopCondition()307 static ShaderCapsPointer AddAndTrueToLoopCondition() { 308 ShaderCapsPointer result = MakeShaderCaps(); 309 result->fVersionDeclString = "#version 400"; 310 result->fAddAndTrueToLoopCondition = true; 311 return result; 312 } 313 CannotUseFractForNegativeValues()314 static ShaderCapsPointer CannotUseFractForNegativeValues() { 315 ShaderCapsPointer result = MakeShaderCaps(); 316 result->fVersionDeclString = "#version 400"; 317 result->fCanUseFractForNegativeValues = false; 318 return result; 319 } 320 CannotUseFragCoord()321 static ShaderCapsPointer CannotUseFragCoord() { 322 ShaderCapsPointer result = MakeShaderCaps(); 323 result->fVersionDeclString = "#version 400"; 324 result->fCanUseFragCoord = false; 325 return result; 326 } 327 CannotUseMinAndAbsTogether()328 static ShaderCapsPointer CannotUseMinAndAbsTogether() { 329 ShaderCapsPointer result = MakeShaderCaps(); 330 result->fVersionDeclString = "#version 400"; 331 result->fCanUseMinAndAbsTogether = false; 332 return result; 333 } 334 EmulateAbsIntFunction()335 static ShaderCapsPointer EmulateAbsIntFunction() { 336 ShaderCapsPointer result = MakeShaderCaps(); 337 result->fVersionDeclString = "#version 400"; 338 result->fEmulateAbsIntFunction = true; 339 return result; 340 } 341 FramebufferFetchSupport()342 static ShaderCapsPointer FramebufferFetchSupport() { 343 ShaderCapsPointer result = MakeShaderCaps(); 344 result->fFBFetchSupport = true; 345 result->fFBFetchColorName = "gl_LastFragData[0]"; 346 return result; 347 } 348 IncompleteShortIntPrecision()349 static ShaderCapsPointer IncompleteShortIntPrecision() { 350 ShaderCapsPointer result = MakeShaderCaps(); 351 result->fVersionDeclString = "#version 310es"; 352 result->fUsesPrecisionModifiers = true; 353 result->fIncompleteShortIntPrecision = true; 354 return result; 355 } 356 MustForceNegatedAtanParamToFloat()357 static ShaderCapsPointer MustForceNegatedAtanParamToFloat() { 358 ShaderCapsPointer result = MakeShaderCaps(); 359 result->fVersionDeclString = "#version 400"; 360 result->fMustForceNegatedAtanParamToFloat = true; 361 return result; 362 } 363 MustForceNegatedLdexpParamToMultiply()364 static ShaderCapsPointer MustForceNegatedLdexpParamToMultiply() { 365 ShaderCapsPointer result = MakeShaderCaps(); 366 result->fVersionDeclString = "#version 400"; 367 result->fMustForceNegatedLdexpParamToMultiply = true; 368 return result; 369 } 370 MustGuardDivisionEvenAfterExplicitZeroCheck()371 static ShaderCapsPointer MustGuardDivisionEvenAfterExplicitZeroCheck() { 372 ShaderCapsPointer result = MakeShaderCaps(); 373 result->fMustGuardDivisionEvenAfterExplicitZeroCheck = true; 374 return result; 375 } 376 RemovePowWithConstantExponent()377 static ShaderCapsPointer RemovePowWithConstantExponent() { 378 ShaderCapsPointer result = MakeShaderCaps(); 379 result->fVersionDeclString = "#version 400"; 380 result->fRemovePowWithConstantExponent = true; 381 return result; 382 } 383 RewriteDoWhileLoops()384 static ShaderCapsPointer RewriteDoWhileLoops() { 385 ShaderCapsPointer result = MakeShaderCaps(); 386 result->fVersionDeclString = "#version 400"; 387 result->fRewriteDoWhileLoops = true; 388 return result; 389 } 390 RewriteMatrixComparisons()391 static ShaderCapsPointer RewriteMatrixComparisons() { 392 ShaderCapsPointer result = MakeShaderCaps(); 393 result->fRewriteMatrixComparisons = true; 394 result->fUsesPrecisionModifiers = true; 395 return result; 396 } 397 RewriteMatrixVectorMultiply()398 static ShaderCapsPointer RewriteMatrixVectorMultiply() { 399 ShaderCapsPointer result = MakeShaderCaps(); 400 result->fVersionDeclString = "#version 400"; 401 result->fRewriteMatrixVectorMultiply = true; 402 return result; 403 } 404 RewriteSwitchStatements()405 static ShaderCapsPointer RewriteSwitchStatements() { 406 ShaderCapsPointer result = MakeShaderCaps(); 407 result->fVersionDeclString = "#version 400"; 408 result->fRewriteSwitchStatements = true; 409 return result; 410 } 411 SampleMaskSupport()412 static ShaderCapsPointer SampleMaskSupport() { 413 ShaderCapsPointer result = Default(); 414 result->fSampleMaskSupport = true; 415 return result; 416 } 417 ShaderDerivativeExtensionString()418 static ShaderCapsPointer ShaderDerivativeExtensionString() { 419 ShaderCapsPointer result = MakeShaderCaps(); 420 result->fVersionDeclString = "#version 400"; 421 result->fShaderDerivativeSupport = true; 422 result->fShaderDerivativeExtensionString = "GL_OES_standard_derivatives"; 423 result->fUsesPrecisionModifiers = true; 424 return result; 425 } 426 UnfoldShortCircuitAsTernary()427 static ShaderCapsPointer UnfoldShortCircuitAsTernary() { 428 ShaderCapsPointer result = MakeShaderCaps(); 429 result->fVersionDeclString = "#version 400"; 430 result->fUnfoldShortCircuitAsTernary = true; 431 return result; 432 } 433 UsesPrecisionModifiers()434 static ShaderCapsPointer UsesPrecisionModifiers() { 435 ShaderCapsPointer result = MakeShaderCaps(); 436 result->fVersionDeclString = "#version 400"; 437 result->fUsesPrecisionModifiers = true; 438 return result; 439 } 440 Version110()441 static ShaderCapsPointer Version110() { 442 ShaderCapsPointer result = MakeShaderCaps(); 443 result->fVersionDeclString = "#version 110"; 444 result->fGLSLGeneration = GrGLSLGeneration::k110_GrGLSLGeneration; 445 return result; 446 } 447 Version450Core()448 static ShaderCapsPointer Version450Core() { 449 ShaderCapsPointer result = MakeShaderCaps(); 450 result->fVersionDeclString = "#version 450 core"; 451 return result; 452 } 453 454 private: 455 static ShaderCapsPointer MakeShaderCaps(); 456 }; 457 458 #if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU 459 bool type_to_grsltype(const Context& context, const Type& type, GrSLType* outType); 460 #endif 461 462 void write_stringstream(const StringStream& d, OutputStream& out); 463 464 } // namespace SkSL 465 466 #endif // SKSL_UTIL 467