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