xref: /aosp_15_r20/external/skia/src/sksl/SkSLUtil.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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