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 "include/core/SkTypes.h" 12 #include "include/sksl/SkSLVersion.h" 13 #include "src/sksl/SkSLGLSL.h" 14 15 #include <memory> 16 17 enum class SkSLType : char; 18 19 namespace SkSL { 20 21 class Context; 22 class OutputStream; 23 class StringStream; 24 class Type; 25 26 struct ShaderCaps { 27 /** 28 * Indicates how GLSL must interact with advanced blend equations. The KHR extension requires 29 * special layout qualifiers in the fragment shader. 30 */ 31 enum AdvBlendEqInteraction { 32 kNotSupported_AdvBlendEqInteraction, //<! No _blend_equation_advanced extension 33 kAutomatic_AdvBlendEqInteraction, //<! No interaction required 34 kGeneralEnable_AdvBlendEqInteraction, //<! layout(blend_support_all_equations) out 35 36 kLast_AdvBlendEqInteraction = kGeneralEnable_AdvBlendEqInteraction 37 }; 38 mustEnableAdvBlendEqsShaderCaps39 bool mustEnableAdvBlendEqs() const { 40 return fAdvBlendEqInteraction >= kGeneralEnable_AdvBlendEqInteraction; 41 } 42 mustDeclareFragmentShaderOutputShaderCaps43 bool mustDeclareFragmentShaderOutput() const { 44 return fGLSLGeneration > SkSL::GLSLGeneration::k110; 45 } 46 47 // Returns the string of an extension that must be enabled in the shader to support 48 // derivatives. If nullptr is returned then no extension needs to be enabled. Before calling 49 // this function, the caller should check that shaderDerivativeSupport exists. shaderDerivativeExtensionStringShaderCaps50 const char* shaderDerivativeExtensionString() const { 51 SkASSERT(this->fShaderDerivativeSupport); 52 return fShaderDerivativeExtensionString; 53 } 54 55 // This returns the name of an extension that must be enabled in the shader to support external 56 // textures. In some cases, two extensions must be enabled - the second extension is returned 57 // by secondExternalTextureExtensionString(). If that function returns nullptr, then only one 58 // extension is required. externalTextureExtensionStringShaderCaps59 const char* externalTextureExtensionString() const { 60 SkASSERT(this->fExternalTextureSupport); 61 return fExternalTextureExtensionString; 62 } 63 secondExternalTextureExtensionStringShaderCaps64 const char* secondExternalTextureExtensionString() const { 65 SkASSERT(this->fExternalTextureSupport); 66 return fSecondExternalTextureExtensionString; 67 } 68 69 /** 70 * SkSL 300 requires support for derivatives, nonsquare matrices and bitwise integer operations. 71 */ supportedSkSLVerionShaderCaps72 SkSL::Version supportedSkSLVerion() const { 73 if (fShaderDerivativeSupport && fNonsquareMatrixSupport && fIntegerSupport && 74 fGLSLGeneration >= SkSL::GLSLGeneration::k330) { 75 return SkSL::Version::k300; 76 } 77 return SkSL::Version::k100; 78 } 79 supportsDistanceFieldTextShaderCaps80 bool supportsDistanceFieldText() const { return fShaderDerivativeSupport; } 81 82 SkSL::GLSLGeneration fGLSLGeneration = SkSL::GLSLGeneration::k330; 83 84 bool fShaderDerivativeSupport = false; 85 /** Enables sampleGrad and sampleLod functions that don't rely on implicit derivatives */ 86 bool fExplicitTextureLodSupport = false; 87 /** Indicates true 32-bit integer support, with unsigned types and bitwise operations */ 88 bool fIntegerSupport = false; 89 bool fNonsquareMatrixSupport = false; 90 /** asinh(), acosh(), atanh() */ 91 bool fInverseHyperbolicSupport = false; 92 bool fFBFetchSupport = false; 93 bool fFBFetchNeedsCustomOutput = false; 94 bool fUsesPrecisionModifiers = false; 95 bool fFlatInterpolationSupport = false; 96 bool fNoPerspectiveInterpolationSupport = false; 97 bool fSampleMaskSupport = false; 98 bool fExternalTextureSupport = false; 99 bool fFloatIs32Bits = true; 100 101 // isinf() is defined, and floating point infinities are handled according to IEEE standards. 102 bool fInfinitySupport = false; 103 104 // Used by SkSL to know when to generate polyfills. 105 bool fBuiltinFMASupport = true; 106 bool fBuiltinDeterminantSupport = true; 107 108 // Used for specific driver bug work arounds 109 bool fCanUseMinAndAbsTogether = true; 110 bool fCanUseFractForNegativeValues = true; 111 bool fMustForceNegatedAtanParamToFloat = false; 112 bool fMustForceNegatedLdexpParamToMultiply = false; // http://skbug.com/12076 113 // Returns whether a device incorrectly implements atan(y,x) as atan(y/x) 114 bool fAtan2ImplementedAsAtanYOverX = false; 115 // If this returns true some operation (could be a no op) must be called between floor and abs 116 // to make sure the driver compiler doesn't inline them together which can cause a driver bug in 117 // the shader. 118 bool fMustDoOpBetweenFloorAndAbs = false; 119 // The D3D shader compiler, when targeting PS 3.0 (ie within ANGLE) fails to compile certain 120 // constructs. See detailed comments in GrGLCaps.cpp. 121 bool fMustGuardDivisionEvenAfterExplicitZeroCheck = false; 122 // If false, SkSL uses a workaround so that sk_FragCoord doesn't actually query gl_FragCoord 123 bool fCanUseFragCoord = true; 124 // If true, short ints can't represent every integer in the 16-bit two's complement range as 125 // required by the spec. SKSL will always emit full ints. 126 bool fIncompleteShortIntPrecision = false; 127 // If true, then conditions in for loops need "&& true" to work around driver bugs. 128 bool fAddAndTrueToLoopCondition = false; 129 // If true, then expressions such as "x && y" or "x || y" are rewritten as ternary to work 130 // around driver bugs. 131 bool fUnfoldShortCircuitAsTernary = false; 132 bool fEmulateAbsIntFunction = false; 133 bool fRewriteDoWhileLoops = false; 134 bool fRewriteSwitchStatements = false; 135 bool fRemovePowWithConstantExponent = false; 136 // The Android emulator claims samplerExternalOES is an unknown type if a default precision 137 // statement is made for the type. 138 bool fNoDefaultPrecisionForExternalSamplers = false; 139 // ARM GPUs calculate `matrix * vector` in SPIR-V at full precision, even when the inputs are 140 // RelaxedPrecision. Rewriting the multiply as a sum of vector*scalar fixes this. (skia:11769) 141 bool fRewriteMatrixVectorMultiply = false; 142 // Rewrites matrix equality comparisons to avoid an Adreno driver bug. (skia:11308) 143 bool fRewriteMatrixComparisons = false; 144 // Strips const from function parameters in the GLSL code generator. (skia:13858) 145 bool fRemoveConstFromFunctionParameters = false; 146 147 const char* fVersionDeclString = ""; 148 149 const char* fShaderDerivativeExtensionString = nullptr; 150 const char* fExternalTextureExtensionString = nullptr; 151 const char* fSecondExternalTextureExtensionString = nullptr; 152 const char* fFBFetchColorName = nullptr; 153 154 AdvBlendEqInteraction fAdvBlendEqInteraction = kNotSupported_AdvBlendEqInteraction; 155 }; 156 157 // Various sets of caps for use in tests 158 class ShaderCapsFactory { 159 public: Default()160 static const ShaderCaps* Default() { 161 static const SkSL::ShaderCaps* sCaps = [] { 162 std::unique_ptr<ShaderCaps> caps = MakeShaderCaps(); 163 caps->fVersionDeclString = "#version 400"; 164 caps->fShaderDerivativeSupport = true; 165 return caps.release(); 166 }(); 167 return sCaps; 168 } 169 Standalone()170 static const ShaderCaps* Standalone() { 171 static const SkSL::ShaderCaps* sCaps = MakeShaderCaps().release(); 172 return sCaps; 173 } 174 175 protected: 176 static std::unique_ptr<ShaderCaps> MakeShaderCaps(); 177 }; 178 179 #if !defined(SKSL_STANDALONE) && (defined(SK_GANESH) || defined(SK_GRAPHITE)) 180 bool type_to_sksltype(const Context& context, const Type& type, SkSLType* outType); 181 #endif 182 183 void write_stringstream(const StringStream& d, OutputStream& out); 184 185 } // namespace SkSL 186 187 #endif // SKSL_UTIL 188