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 fDualSourceBlendingSupport = false; 85 bool fShaderDerivativeSupport = false; 86 /** Enables sampleGrad and sampleLod functions that don't rely on implicit derivatives */ 87 bool fExplicitTextureLodSupport = false; 88 /** Indicates true 32-bit integer support, with unsigned types and bitwise operations */ 89 bool fIntegerSupport = false; 90 bool fNonsquareMatrixSupport = false; 91 /** asinh(), acosh(), atanh() */ 92 bool fInverseHyperbolicSupport = false; 93 bool fFBFetchSupport = false; 94 bool fFBFetchNeedsCustomOutput = false; 95 bool fUsesPrecisionModifiers = false; 96 bool fFlatInterpolationSupport = false; 97 bool fNoPerspectiveInterpolationSupport = false; 98 bool fSampleMaskSupport = false; 99 bool fExternalTextureSupport = false; 100 bool fFloatIs32Bits = true; 101 102 // isinf() is defined, and floating point infinities are handled according to IEEE standards. 103 bool fInfinitySupport = false; 104 105 // Used by SkSL to know when to generate polyfills. 106 bool fBuiltinFMASupport = true; 107 bool fBuiltinDeterminantSupport = true; 108 109 // Used for specific driver bug work arounds 110 bool fCanUseVoidInSequenceExpressions = true; 111 bool fCanUseMinAndAbsTogether = true; 112 bool fCanUseFractForNegativeValues = true; 113 bool fMustForceNegatedAtanParamToFloat = false; 114 bool fMustForceNegatedLdexpParamToMultiply = false; // http://skbug.com/12076 115 // Returns whether a device incorrectly implements atan(y,x) as atan(y/x) 116 bool fAtan2ImplementedAsAtanYOverX = false; 117 // If this returns true some operation (could be a no op) must be called between floor and abs 118 // to make sure the driver compiler doesn't inline them together which can cause a driver bug in 119 // the shader. 120 bool fMustDoOpBetweenFloorAndAbs = false; 121 // The D3D shader compiler, when targeting PS 3.0 (ie within ANGLE) fails to compile certain 122 // constructs. See detailed comments in GrGLCaps.cpp. 123 bool fMustGuardDivisionEvenAfterExplicitZeroCheck = false; 124 // If false, SkSL uses a workaround so that sk_FragCoord doesn't actually query gl_FragCoord 125 bool fCanUseFragCoord = true; 126 // If true, then conditions in for loops need "&& true" to work around driver bugs. 127 bool fAddAndTrueToLoopCondition = false; 128 // If true, then expressions such as "x && y" or "x || y" are rewritten as ternary to work 129 // around driver bugs. 130 bool fUnfoldShortCircuitAsTernary = false; 131 bool fEmulateAbsIntFunction = false; 132 bool fRewriteDoWhileLoops = false; 133 bool fRewriteSwitchStatements = false; 134 bool fRemovePowWithConstantExponent = false; 135 // The Android emulator claims samplerExternalOES is an unknown type if a default precision 136 // statement is made for the type. 137 bool fNoDefaultPrecisionForExternalSamplers = false; 138 // ARM GPUs calculate `matrix * vector` in SPIR-V at full precision, even when the inputs are 139 // RelaxedPrecision. Rewriting the multiply as a sum of vector*scalar fixes this. (skia:11769) 140 bool fRewriteMatrixVectorMultiply = false; 141 // Rewrites matrix equality comparisons to avoid an Adreno driver bug. (skia:11308) 142 bool fRewriteMatrixComparisons = false; 143 // Strips const from function parameters in the GLSL code generator. (skia:13858) 144 bool fRemoveConstFromFunctionParameters = false; 145 // On some Android devices colors aren't accurate enough for the double lookup in the 146 // Perlin noise shader. This workaround aggressively snaps colors to multiples of 1/255. 147 bool fPerlinNoiseRoundingFix = false; 148 // Vulkan requires certain builtin variables be present, even if they're unused. At one time, 149 // validation errors would result if sk_Clockwise was missing. Now, it's just (Adreno) driver 150 // bugs that drop or corrupt draws if they're missing. 151 bool fMustDeclareFragmentFrontFacing = false; 152 // SPIR-V currently doesn't handle different array strides being passed in to a fixed sized 153 // array function parameter, so fForceStd430ArrayLayout will make all array strides conform 154 // to std430 stride alignment rules. 155 bool fForceStd430ArrayLayout = false; 156 157 const char* fVersionDeclString = ""; 158 159 const char* fShaderDerivativeExtensionString = nullptr; 160 const char* fExternalTextureExtensionString = nullptr; 161 const char* fSecondExternalTextureExtensionString = nullptr; 162 const char* fFBFetchColorName = nullptr; 163 164 AdvBlendEqInteraction fAdvBlendEqInteraction = kNotSupported_AdvBlendEqInteraction; 165 }; 166 167 // Various sets of caps for use in tests 168 class ShaderCapsFactory { 169 public: Default()170 static const ShaderCaps* Default() { 171 static const SkSL::ShaderCaps* sCaps = [] { 172 std::unique_ptr<ShaderCaps> caps = MakeShaderCaps(); 173 caps->fVersionDeclString = "#version 400"; 174 caps->fShaderDerivativeSupport = true; 175 return caps.release(); 176 }(); 177 return sCaps; 178 } 179 Standalone()180 static const ShaderCaps* Standalone() { 181 static const SkSL::ShaderCaps* sCaps = MakeShaderCaps().release(); 182 return sCaps; 183 } 184 185 protected: 186 static std::unique_ptr<ShaderCaps> MakeShaderCaps(); 187 }; 188 189 bool type_to_sksltype(const Context& context, const Type& type, SkSLType* outType); 190 191 void write_stringstream(const StringStream& d, OutputStream& out); 192 193 } // namespace SkSL 194 195 #endif // SKSL_UTIL 196