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/core/SkSLTypeShared.h" 17 #include "src/sksl/SkSLGLSL.h" 18 #include "src/sksl/SkSLLexer.h" 19 20 #ifndef SKSL_STANDALONE 21 #include "include/core/SkTypes.h" 22 #if SK_SUPPORT_GPU 23 #include "include/gpu/GrContextOptions.h" 24 #include "include/private/GrTypesPriv.h" 25 #endif // SK_SUPPORT_GPU 26 #endif // SKSL_STANDALONE 27 28 namespace SkSL { 29 30 class Context; 31 class OutputStream; 32 class ShaderCapsFactory; 33 class StringStream; 34 class Type; 35 36 struct ShaderCaps { 37 /** 38 * Indicates how GLSL must interact with advanced blend equations. The KHR extension requires 39 * special layout qualifiers in the fragment shader. 40 */ 41 enum AdvBlendEqInteraction { 42 kNotSupported_AdvBlendEqInteraction, //<! No _blend_equation_advanced extension 43 kAutomatic_AdvBlendEqInteraction, //<! No interaction required 44 kGeneralEnable_AdvBlendEqInteraction, //<! layout(blend_support_all_equations) out 45 46 kLast_AdvBlendEqInteraction = kGeneralEnable_AdvBlendEqInteraction 47 }; 48 49 // 50 // TODO: Remove these accessors 51 // shaderDerivativeSupportShaderCaps52 bool shaderDerivativeSupport() const { return fShaderDerivativeSupport; } nonsquareMatrixSupportShaderCaps53 bool nonsquareMatrixSupport() const { return fNonsquareMatrixSupport; } 54 55 /** Indicates true 32-bit integer support, with unsigned types and bitwise operations */ integerSupportShaderCaps56 bool integerSupport() const { return fIntegerSupport; } 57 58 /** asinh(), acosh(), atanh() */ inverseHyperbolicSupportShaderCaps59 bool inverseHyperbolicSupport() const { return fInverseHyperbolicSupport; } 60 61 /** 62 * Some helper functions for encapsulating various extensions to read FB Buffer on openglES 63 * 64 * TODO: On desktop opengl 4.2+ we can achieve something similar to this effect 65 */ fbFetchSupportShaderCaps66 bool fbFetchSupport() const { return fFBFetchSupport; } 67 fbFetchNeedsCustomOutputShaderCaps68 bool fbFetchNeedsCustomOutput() const { return fFBFetchNeedsCustomOutput; } 69 versionDeclStringShaderCaps70 const char* versionDeclString() const { return fVersionDeclString; } 71 fbFetchColorNameShaderCaps72 const char* fbFetchColorName() const { return fFBFetchColorName; } 73 flatInterpolationSupportShaderCaps74 bool flatInterpolationSupport() const { return fFlatInterpolationSupport; } 75 noperspectiveInterpolationSupportShaderCaps76 bool noperspectiveInterpolationSupport() const { return fNoPerspectiveInterpolationSupport; } 77 sampleMaskSupportShaderCaps78 bool sampleMaskSupport() const { return fSampleMaskSupport; } 79 externalTextureSupportShaderCaps80 bool externalTextureSupport() const { return fExternalTextureSupport; } 81 floatIs32BitsShaderCaps82 bool floatIs32Bits() const { return fFloatIs32Bits; } 83 84 // SkSL only. builtinFMASupportShaderCaps85 bool builtinFMASupport() const { return fBuiltinFMASupport; } 86 builtinDeterminantSupportShaderCaps87 bool builtinDeterminantSupport() const { return fBuiltinDeterminantSupport; } 88 advBlendEqInteractionShaderCaps89 AdvBlendEqInteraction advBlendEqInteraction() const { return fAdvBlendEqInteraction; } 90 mustEnableAdvBlendEqsShaderCaps91 bool mustEnableAdvBlendEqs() const { 92 return fAdvBlendEqInteraction >= kGeneralEnable_AdvBlendEqInteraction; 93 } 94 mustDeclareFragmentShaderOutputShaderCaps95 bool mustDeclareFragmentShaderOutput() const { 96 return fGLSLGeneration > SkSL::GLSLGeneration::k110; 97 } 98 usesPrecisionModifiersShaderCaps99 bool usesPrecisionModifiers() const { return fUsesPrecisionModifiers; } 100 101 // Returns whether we can use the glsl function any() in our shader code. canUseAnyFunctionInShaderShaderCaps102 bool canUseAnyFunctionInShader() const { return fCanUseAnyFunctionInShader; } 103 canUseMinAndAbsTogetherShaderCaps104 bool canUseMinAndAbsTogether() const { return fCanUseMinAndAbsTogether; } 105 canUseFractForNegativeValuesShaderCaps106 bool canUseFractForNegativeValues() const { return fCanUseFractForNegativeValues; } 107 mustForceNegatedAtanParamToFloatShaderCaps108 bool mustForceNegatedAtanParamToFloat() const { return fMustForceNegatedAtanParamToFloat; } 109 110 // http://skbug.com/12076 mustForceNegatedLdexpParamToMultiplyShaderCaps111 bool mustForceNegatedLdexpParamToMultiply() const { 112 return fMustForceNegatedLdexpParamToMultiply; 113 } 114 115 // Returns whether a device incorrectly implements atan(y,x) as atan(y/x) atan2ImplementedAsAtanYOverXShaderCaps116 bool atan2ImplementedAsAtanYOverX() const { return fAtan2ImplementedAsAtanYOverX; } 117 118 // If this returns true some operation (could be a no op) must be called between floor and abs 119 // to make sure the driver compiler doesn't inline them together which can cause a driver bug in 120 // the shader. mustDoOpBetweenFloorAndAbsShaderCaps121 bool mustDoOpBetweenFloorAndAbs() const { return fMustDoOpBetweenFloorAndAbs; } 122 123 // If false, SkSL uses a workaround so that sk_FragCoord doesn't actually query gl_FragCoord canUseFragCoordShaderCaps124 bool canUseFragCoord() const { return fCanUseFragCoord; } 125 126 // If true, short ints can't represent every integer in the 16-bit two's complement range as 127 // required by the spec. SKSL will always emit full ints. incompleteShortIntPrecisionShaderCaps128 bool incompleteShortIntPrecision() const { return fIncompleteShortIntPrecision; } 129 130 // If true, then conditions in for loops need "&& true" to work around driver bugs. addAndTrueToLoopConditionShaderCaps131 bool addAndTrueToLoopCondition() const { return fAddAndTrueToLoopCondition; } 132 133 // If true, then expressions such as "x && y" or "x || y" are rewritten as 134 // ternary to work around driver bugs. unfoldShortCircuitAsTernaryShaderCaps135 bool unfoldShortCircuitAsTernary() const { return fUnfoldShortCircuitAsTernary; } 136 emulateAbsIntFunctionShaderCaps137 bool emulateAbsIntFunction() const { return fEmulateAbsIntFunction; } 138 rewriteDoWhileLoopsShaderCaps139 bool rewriteDoWhileLoops() const { return fRewriteDoWhileLoops; } 140 rewriteSwitchStatementsShaderCaps141 bool rewriteSwitchStatements() const { return fRewriteSwitchStatements; } 142 removePowWithConstantExponentShaderCaps143 bool removePowWithConstantExponent() const { return fRemovePowWithConstantExponent; } 144 145 // The D3D shader compiler, when targeting PS 3.0 (ie within ANGLE) fails to compile certain 146 // constructs. See detailed comments in GrGLCaps.cpp. mustGuardDivisionEvenAfterExplicitZeroCheckShaderCaps147 bool mustGuardDivisionEvenAfterExplicitZeroCheck() const { 148 return fMustGuardDivisionEvenAfterExplicitZeroCheck; 149 } 150 151 // The Android emulator claims samplerExternalOES is an unknown type if a default precision 152 // statement is made for the type. noDefaultPrecisionForExternalSamplersShaderCaps153 bool noDefaultPrecisionForExternalSamplers() const { 154 return fNoDefaultPrecisionForExternalSamplers; 155 } 156 157 // ARM GPUs calculate `matrix * vector` in SPIR-V at full precision, even when the inputs are 158 // RelaxedPrecision. Rewriting the multiply as a sum of vector*scalar fixes this. (skia:11769) rewriteMatrixVectorMultiplyShaderCaps159 bool rewriteMatrixVectorMultiply() const { 160 return fRewriteMatrixVectorMultiply; 161 } 162 163 // Rewrites matrix equality comparisons to avoid an Adreno driver bug. (skia:11308) rewriteMatrixComparisonsShaderCaps164 bool rewriteMatrixComparisons() const { return fRewriteMatrixComparisons; } 165 166 // By default, SkSL pools IR nodes per-program. To debug memory corruption, it is sometimes 167 // helpful to disable that feature. useNodePoolsShaderCaps168 bool useNodePools() const { return fUseNodePools; } 169 170 // Returns the string of an extension that must be enabled in the shader to support 171 // derivatives. If nullptr is returned then no extension needs to be enabled. Before calling 172 // this function, the caller should check that shaderDerivativeSupport exists. shaderDerivativeExtensionStringShaderCaps173 const char* shaderDerivativeExtensionString() const { 174 SkASSERT(this->shaderDerivativeSupport()); 175 return fShaderDerivativeExtensionString; 176 } 177 178 // This returns the name of an extension that must be enabled in the shader to support external 179 // textures. In some cases, two extensions must be enabled - the second extension is returned 180 // by secondExternalTextureExtensionString(). If that function returns nullptr, then only one 181 // extension is required. externalTextureExtensionStringShaderCaps182 const char* externalTextureExtensionString() const { 183 SkASSERT(this->externalTextureSupport()); 184 return fExternalTextureExtensionString; 185 } 186 secondExternalTextureExtensionStringShaderCaps187 const char* secondExternalTextureExtensionString() const { 188 SkASSERT(this->externalTextureSupport()); 189 return fSecondExternalTextureExtensionString; 190 } 191 generationShaderCaps192 SkSL::GLSLGeneration generation() const { return fGLSLGeneration; } 193 194 SkSL::GLSLGeneration fGLSLGeneration = SkSL::GLSLGeneration::k330; 195 196 bool fShaderDerivativeSupport = false; 197 bool fIntegerSupport = false; 198 bool fNonsquareMatrixSupport = false; 199 bool fInverseHyperbolicSupport = false; 200 bool fFBFetchSupport = false; 201 bool fFBFetchNeedsCustomOutput = false; 202 bool fUsesPrecisionModifiers = false; 203 bool fFlatInterpolationSupport = false; 204 bool fNoPerspectiveInterpolationSupport = false; 205 bool fSampleMaskSupport = false; 206 bool fExternalTextureSupport = false; 207 bool fFloatIs32Bits = true; 208 209 // Used by SkSL to know when to generate polyfills. 210 bool fBuiltinFMASupport = false; 211 bool fBuiltinDeterminantSupport = false; 212 213 // Used for specific driver bug work arounds 214 bool fCanUseAnyFunctionInShader = true; 215 bool fCanUseMinAndAbsTogether = true; 216 bool fCanUseFractForNegativeValues = true; 217 bool fMustForceNegatedAtanParamToFloat = false; 218 bool fMustForceNegatedLdexpParamToMultiply = false; 219 bool fAtan2ImplementedAsAtanYOverX = false; 220 bool fMustDoOpBetweenFloorAndAbs = false; 221 bool fMustGuardDivisionEvenAfterExplicitZeroCheck = false; 222 bool fCanUseFragCoord = true; 223 bool fIncompleteShortIntPrecision = false; 224 bool fAddAndTrueToLoopCondition = false; 225 bool fUnfoldShortCircuitAsTernary = false; 226 bool fEmulateAbsIntFunction = false; 227 bool fRewriteDoWhileLoops = false; 228 bool fRewriteSwitchStatements = false; 229 bool fRemovePowWithConstantExponent = false; 230 bool fNoDefaultPrecisionForExternalSamplers = false; 231 bool fRewriteMatrixVectorMultiply = false; 232 bool fRewriteMatrixComparisons = false; 233 234 // This controls behavior of the SkSL compiler, not the code we generate 235 bool fUseNodePools = true; 236 237 const char* fVersionDeclString = ""; 238 239 const char* fShaderDerivativeExtensionString = nullptr; 240 const char* fExternalTextureExtensionString = nullptr; 241 const char* fSecondExternalTextureExtensionString = nullptr; 242 const char* fFBFetchColorName = nullptr; 243 244 AdvBlendEqInteraction fAdvBlendEqInteraction = kNotSupported_AdvBlendEqInteraction; 245 }; 246 247 // Various sets of caps for use in tests 248 class ShaderCapsFactory { 249 public: Default()250 static std::unique_ptr<ShaderCaps> Default() { 251 std::unique_ptr<ShaderCaps> result = MakeShaderCaps(); 252 result->fVersionDeclString = "#version 400"; 253 result->fShaderDerivativeSupport = true; 254 result->fBuiltinDeterminantSupport = true; 255 return result; 256 } 257 Standalone()258 static std::unique_ptr<ShaderCaps> Standalone() { 259 return MakeShaderCaps(); 260 } 261 AddAndTrueToLoopCondition()262 static std::unique_ptr<ShaderCaps> AddAndTrueToLoopCondition() { 263 std::unique_ptr<ShaderCaps> result = MakeShaderCaps(); 264 result->fVersionDeclString = "#version 400"; 265 result->fAddAndTrueToLoopCondition = true; 266 return result; 267 } 268 CannotUseFractForNegativeValues()269 static std::unique_ptr<ShaderCaps> CannotUseFractForNegativeValues() { 270 std::unique_ptr<ShaderCaps> result = MakeShaderCaps(); 271 result->fVersionDeclString = "#version 400"; 272 result->fCanUseFractForNegativeValues = false; 273 return result; 274 } 275 CannotUseFragCoord()276 static std::unique_ptr<ShaderCaps> CannotUseFragCoord() { 277 std::unique_ptr<ShaderCaps> result = MakeShaderCaps(); 278 result->fVersionDeclString = "#version 400"; 279 result->fCanUseFragCoord = false; 280 return result; 281 } 282 CannotUseMinAndAbsTogether()283 static std::unique_ptr<ShaderCaps> CannotUseMinAndAbsTogether() { 284 std::unique_ptr<ShaderCaps> result = MakeShaderCaps(); 285 result->fVersionDeclString = "#version 400"; 286 result->fCanUseMinAndAbsTogether = false; 287 return result; 288 } 289 EmulateAbsIntFunction()290 static std::unique_ptr<ShaderCaps> EmulateAbsIntFunction() { 291 std::unique_ptr<ShaderCaps> result = MakeShaderCaps(); 292 result->fVersionDeclString = "#version 400"; 293 result->fEmulateAbsIntFunction = true; 294 return result; 295 } 296 FramebufferFetchSupport()297 static std::unique_ptr<ShaderCaps> FramebufferFetchSupport() { 298 std::unique_ptr<ShaderCaps> result = MakeShaderCaps(); 299 result->fFBFetchSupport = true; 300 result->fFBFetchColorName = "gl_LastFragData[0]"; 301 return result; 302 } 303 IncompleteShortIntPrecision()304 static std::unique_ptr<ShaderCaps> IncompleteShortIntPrecision() { 305 std::unique_ptr<ShaderCaps> result = MakeShaderCaps(); 306 result->fVersionDeclString = "#version 310es"; 307 result->fUsesPrecisionModifiers = true; 308 result->fIncompleteShortIntPrecision = true; 309 return result; 310 } 311 MustForceNegatedAtanParamToFloat()312 static std::unique_ptr<ShaderCaps> MustForceNegatedAtanParamToFloat() { 313 std::unique_ptr<ShaderCaps> result = MakeShaderCaps(); 314 result->fVersionDeclString = "#version 400"; 315 result->fMustForceNegatedAtanParamToFloat = true; 316 return result; 317 } 318 MustForceNegatedLdexpParamToMultiply()319 static std::unique_ptr<ShaderCaps> MustForceNegatedLdexpParamToMultiply() { 320 std::unique_ptr<ShaderCaps> result = MakeShaderCaps(); 321 result->fVersionDeclString = "#version 400"; 322 result->fMustForceNegatedLdexpParamToMultiply = true; 323 return result; 324 } 325 MustGuardDivisionEvenAfterExplicitZeroCheck()326 static std::unique_ptr<ShaderCaps> MustGuardDivisionEvenAfterExplicitZeroCheck() { 327 std::unique_ptr<ShaderCaps> result = MakeShaderCaps(); 328 result->fMustGuardDivisionEvenAfterExplicitZeroCheck = true; 329 return result; 330 } 331 RemovePowWithConstantExponent()332 static std::unique_ptr<ShaderCaps> RemovePowWithConstantExponent() { 333 std::unique_ptr<ShaderCaps> result = MakeShaderCaps(); 334 result->fVersionDeclString = "#version 400"; 335 result->fRemovePowWithConstantExponent = true; 336 return result; 337 } 338 RewriteDoWhileLoops()339 static std::unique_ptr<ShaderCaps> RewriteDoWhileLoops() { 340 std::unique_ptr<ShaderCaps> result = MakeShaderCaps(); 341 result->fVersionDeclString = "#version 400"; 342 result->fRewriteDoWhileLoops = true; 343 return result; 344 } 345 RewriteMatrixComparisons()346 static std::unique_ptr<ShaderCaps> RewriteMatrixComparisons() { 347 std::unique_ptr<ShaderCaps> result = MakeShaderCaps(); 348 result->fRewriteMatrixComparisons = true; 349 result->fUsesPrecisionModifiers = true; 350 return result; 351 } 352 RewriteMatrixVectorMultiply()353 static std::unique_ptr<ShaderCaps> RewriteMatrixVectorMultiply() { 354 std::unique_ptr<ShaderCaps> result = MakeShaderCaps(); 355 result->fVersionDeclString = "#version 400"; 356 result->fRewriteMatrixVectorMultiply = true; 357 return result; 358 } 359 RewriteSwitchStatements()360 static std::unique_ptr<ShaderCaps> RewriteSwitchStatements() { 361 std::unique_ptr<ShaderCaps> result = MakeShaderCaps(); 362 result->fVersionDeclString = "#version 400"; 363 result->fRewriteSwitchStatements = true; 364 return result; 365 } 366 SampleMaskSupport()367 static std::unique_ptr<ShaderCaps> SampleMaskSupport() { 368 std::unique_ptr<ShaderCaps> result = Default(); 369 result->fSampleMaskSupport = true; 370 return result; 371 } 372 ShaderDerivativeExtensionString()373 static std::unique_ptr<ShaderCaps> ShaderDerivativeExtensionString() { 374 std::unique_ptr<ShaderCaps> result = MakeShaderCaps(); 375 result->fVersionDeclString = "#version 400"; 376 result->fShaderDerivativeSupport = true; 377 result->fShaderDerivativeExtensionString = "GL_OES_standard_derivatives"; 378 result->fUsesPrecisionModifiers = true; 379 return result; 380 } 381 UnfoldShortCircuitAsTernary()382 static std::unique_ptr<ShaderCaps> UnfoldShortCircuitAsTernary() { 383 std::unique_ptr<ShaderCaps> result = MakeShaderCaps(); 384 result->fVersionDeclString = "#version 400"; 385 result->fUnfoldShortCircuitAsTernary = true; 386 return result; 387 } 388 UsesPrecisionModifiers()389 static std::unique_ptr<ShaderCaps> UsesPrecisionModifiers() { 390 std::unique_ptr<ShaderCaps> result = MakeShaderCaps(); 391 result->fVersionDeclString = "#version 400"; 392 result->fUsesPrecisionModifiers = true; 393 return result; 394 } 395 Version110()396 static std::unique_ptr<ShaderCaps> Version110() { 397 std::unique_ptr<ShaderCaps> result = MakeShaderCaps(); 398 result->fVersionDeclString = "#version 110"; 399 result->fGLSLGeneration = SkSL::GLSLGeneration::k110; 400 return result; 401 } 402 Version450Core()403 static std::unique_ptr<ShaderCaps> Version450Core() { 404 std::unique_ptr<ShaderCaps> result = MakeShaderCaps(); 405 result->fVersionDeclString = "#version 450 core"; 406 return result; 407 } 408 409 private: 410 static std::unique_ptr<ShaderCaps> MakeShaderCaps(); 411 }; 412 413 #if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU 414 bool type_to_sksltype(const Context& context, const Type& type, SkSLType* outType); 415 #endif 416 417 void write_stringstream(const StringStream& d, OutputStream& out); 418 419 } // namespace SkSL 420 421 #endif // SKSL_UTIL 422