2 * Copyright 2016 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
11 #include "include/sksl/SkSLVersion.h"
12 #include "src/core/SkSLTypeShared.h"
13 #include "src/sksl/SkSLGLSL.h"
17 #ifndef SKSL_STANDALONE
18 #include "include/core/SkTypes.h"
19 #endif // SKSL_STANDALONE
30 * Indicates how GLSL must interact with advanced blend equations. The KHR extension requires
31 * special layout qualifiers in the fragment shader.
33 enum AdvBlendEqInteraction {
34 kNotSupported_AdvBlendEqInteraction, //<! No _blend_equation_advanced extension
35 kAutomatic_AdvBlendEqInteraction, //<! No interaction required
36 kGeneralEnable_AdvBlendEqInteraction, //<! layout(blend_support_all_equations) out
38 kLast_AdvBlendEqInteraction = kGeneralEnable_AdvBlendEqInteraction
42 // TODO: Remove these accessors
44 bool shaderDerivativeSupport() const { return fShaderDerivativeSupport; }
45 bool nonsquareMatrixSupport() const { return fNonsquareMatrixSupport; }
47 /** Indicates true 32-bit integer support, with unsigned types and bitwise operations */
48 bool integerSupport() const { return fIntegerSupport; }
50 /** asinh(), acosh(), atanh() */
51 bool inverseHyperbolicSupport() const { return fInverseHyperbolicSupport; }
54 * Some helper functions for encapsulating various extensions to read FB Buffer on openglES
56 * TODO: On desktop opengl 4.2+ we can achieve something similar to this effect
58 bool fbFetchSupport() const { return fFBFetchSupport; }
60 bool fbFetchNeedsCustomOutput() const { return fFBFetchNeedsCustomOutput; }
62 const char* versionDeclString() const { return fVersionDeclString; }
64 const char* fbFetchColorName() const { return fFBFetchColorName; }
66 bool flatInterpolationSupport() const { return fFlatInterpolationSupport; }
68 bool noperspectiveInterpolationSupport() const { return fNoPerspectiveInterpolationSupport; }
70 bool sampleMaskSupport() const { return fSampleMaskSupport; }
72 bool externalTextureSupport() const { return fExternalTextureSupport; }
74 bool floatIs32Bits() const { return fFloatIs32Bits; }
77 bool builtinFMASupport() const { return fBuiltinFMASupport; }
79 bool builtinDeterminantSupport() const { return fBuiltinDeterminantSupport; }
81 AdvBlendEqInteraction advBlendEqInteraction() const { return fAdvBlendEqInteraction; }
83 bool mustEnableAdvBlendEqs() const {
84 return fAdvBlendEqInteraction >= kGeneralEnable_AdvBlendEqInteraction;
87 bool mustDeclareFragmentShaderOutput() const {
88 return fGLSLGeneration > SkSL::GLSLGeneration::k110;
91 bool usesPrecisionModifiers() const { return fUsesPrecisionModifiers; }
93 // Returns whether we can use the glsl function any() in our shader code.
94 bool canUseAnyFunctionInShader() const { return fCanUseAnyFunctionInShader; }
96 bool canUseMinAndAbsTogether() const { return fCanUseMinAndAbsTogether; }
98 bool canUseFractForNegativeValues() const { return fCanUseFractForNegativeValues; }
100 bool mustForceNegatedAtanParamToFloat() const { return fMustForceNegatedAtanParamToFloat; }
102 // http://skbug.com/12076
103 bool mustForceNegatedLdexpParamToMultiply() const {
104 return fMustForceNegatedLdexpParamToMultiply;
107 // Returns whether a device incorrectly implements atan(y,x) as atan(y/x)
108 bool atan2ImplementedAsAtanYOverX() const { return fAtan2ImplementedAsAtanYOverX; }
110 // If this returns true some operation (could be a no op) must be called between floor and abs
111 // to make sure the driver compiler doesn't inline them together which can cause a driver bug in
113 bool mustDoOpBetweenFloorAndAbs() const { return fMustDoOpBetweenFloorAndAbs; }
115 // If false, SkSL uses a workaround so that sk_FragCoord doesn't actually query gl_FragCoord
116 bool canUseFragCoord() const { return fCanUseFragCoord; }
118 // If true, short ints can't represent every integer in the 16-bit two's complement range as
119 // required by the spec. SKSL will always emit full ints.
120 bool incompleteShortIntPrecision() const { return fIncompleteShortIntPrecision; }
122 // If true, then conditions in for loops need "&& true" to work around driver bugs.
123 bool addAndTrueToLoopCondition() const { return fAddAndTrueToLoopCondition; }
125 // If true, then expressions such as "x && y" or "x || y" are rewritten as
126 // ternary to work around driver bugs.
127 bool unfoldShortCircuitAsTernary() const { return fUnfoldShortCircuitAsTernary; }
129 bool emulateAbsIntFunction() const { return fEmulateAbsIntFunction; }
131 bool rewriteDoWhileLoops() const { return fRewriteDoWhileLoops; }
133 bool rewriteSwitchStatements() const { return fRewriteSwitchStatements; }
135 bool removePowWithConstantExponent() const { return fRemovePowWithConstantExponent; }
137 // The D3D shader compiler, when targeting PS 3.0 (ie within ANGLE) fails to compile certain
138 // constructs. See detailed comments in GrGLCaps.cpp.
139 bool mustGuardDivisionEvenAfterExplicitZeroCheck() const {
140 return fMustGuardDivisionEvenAfterExplicitZeroCheck;
143 // The Android emulator claims samplerExternalOES is an unknown type if a default precision
144 // statement is made for the type.
145 bool noDefaultPrecisionForExternalSamplers() const {
146 return fNoDefaultPrecisionForExternalSamplers;
149 // ARM GPUs calculate `matrix * vector` in SPIR-V at full precision, even when the inputs are
150 // RelaxedPrecision. Rewriting the multiply as a sum of vector*scalar fixes this. (skia:11769)
151 bool rewriteMatrixVectorMultiply() const {
152 return fRewriteMatrixVectorMultiply;
155 // Rewrites matrix equality comparisons to avoid an Adreno driver bug. (skia:11308)
156 bool rewriteMatrixComparisons() const { return fRewriteMatrixComparisons; }
158 // By default, SkSL pools IR nodes per-program. To debug memory corruption, it is sometimes
159 // helpful to disable that feature.
160 bool useNodePools() const { return fUseNodePools; }
162 // Returns the string of an extension that must be enabled in the shader to support
163 // derivatives. If nullptr is returned then no extension needs to be enabled. Before calling
164 // this function, the caller should check that shaderDerivativeSupport exists.
165 const char* shaderDerivativeExtensionString() const {
166 SkASSERT(this->shaderDerivativeSupport());
167 return fShaderDerivativeExtensionString;
170 // This returns the name of an extension that must be enabled in the shader to support external
171 // textures. In some cases, two extensions must be enabled - the second extension is returned
172 // by secondExternalTextureExtensionString(). If that function returns nullptr, then only one
173 // extension is required.
174 const char* externalTextureExtensionString() const {
175 SkASSERT(this->externalTextureSupport());
176 return fExternalTextureExtensionString;
179 const char* secondExternalTextureExtensionString() const {
180 SkASSERT(this->externalTextureSupport());
181 return fSecondExternalTextureExtensionString;
185 * SkSL 300 requires support for derivatives, nonsquare matrices and bitwise integer operations.
187 SkSL::Version supportedSkSLVerion() const {
188 if (fShaderDerivativeSupport && fNonsquareMatrixSupport && fIntegerSupport &&
189 fGLSLGeneration >= SkSL::GLSLGeneration::k330) {
190 return SkSL::Version::k300;
192 return SkSL::Version::k100;
195 SkSL::GLSLGeneration generation() const { return fGLSLGeneration; }
197 SkSL::GLSLGeneration fGLSLGeneration = SkSL::GLSLGeneration::k330;
199 bool fShaderDerivativeSupport = false;
200 bool fIntegerSupport = false;
201 bool fNonsquareMatrixSupport = false;
202 bool fInverseHyperbolicSupport = false;
203 bool fFBFetchSupport = false;
204 bool fFBFetchNeedsCustomOutput = false;
205 bool fUsesPrecisionModifiers = false;
206 bool fFlatInterpolationSupport = false;
207 bool fNoPerspectiveInterpolationSupport = false;
208 bool fSampleMaskSupport = false;
209 bool fExternalTextureSupport = false;
210 bool fFloatIs32Bits = true;
212 // Used by SkSL to know when to generate polyfills.
213 bool fBuiltinFMASupport = false;
214 bool fBuiltinDeterminantSupport = false;
216 // Used for specific driver bug work arounds
217 bool fCanUseAnyFunctionInShader = true;
218 bool fCanUseMinAndAbsTogether = true;
219 bool fCanUseFractForNegativeValues = true;
220 bool fMustForceNegatedAtanParamToFloat = false;
221 bool fMustForceNegatedLdexpParamToMultiply = false;
222 bool fAtan2ImplementedAsAtanYOverX = false;
223 bool fMustDoOpBetweenFloorAndAbs = false;
224 bool fMustGuardDivisionEvenAfterExplicitZeroCheck = false;
225 bool fCanUseFragCoord = true;
226 bool fIncompleteShortIntPrecision = false;
227 bool fAddAndTrueToLoopCondition = false;
228 bool fUnfoldShortCircuitAsTernary = false;
229 bool fEmulateAbsIntFunction = false;
230 bool fRewriteDoWhileLoops = false;
231 bool fRewriteSwitchStatements = false;
232 bool fRemovePowWithConstantExponent = false;
233 bool fNoDefaultPrecisionForExternalSamplers = false;
234 bool fRewriteMatrixVectorMultiply = false;
235 bool fRewriteMatrixComparisons = false;
237 // This controls behavior of the SkSL compiler, not the code we generate
238 bool fUseNodePools = true;
240 const char* fVersionDeclString = "";
242 const char* fShaderDerivativeExtensionString = nullptr;
243 const char* fExternalTextureExtensionString = nullptr;
244 const char* fSecondExternalTextureExtensionString = nullptr;
245 const char* fFBFetchColorName = nullptr;
247 AdvBlendEqInteraction fAdvBlendEqInteraction = kNotSupported_AdvBlendEqInteraction;
250 // Various sets of caps for use in tests
251 class ShaderCapsFactory {
253 static std::unique_ptr<ShaderCaps> Default() {
254 std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
255 result->fVersionDeclString = "#version 400";
256 result->fShaderDerivativeSupport = true;
257 result->fBuiltinDeterminantSupport = true;
261 static std::unique_ptr<ShaderCaps> Standalone() {
262 return MakeShaderCaps();
265 static std::unique_ptr<ShaderCaps> AddAndTrueToLoopCondition() {
266 std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
267 result->fVersionDeclString = "#version 400";
268 result->fAddAndTrueToLoopCondition = true;
272 static std::unique_ptr<ShaderCaps> CannotUseFractForNegativeValues() {
273 std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
274 result->fVersionDeclString = "#version 400";
275 result->fCanUseFractForNegativeValues = false;
279 static std::unique_ptr<ShaderCaps> CannotUseFragCoord() {
280 std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
281 result->fVersionDeclString = "#version 400";
282 result->fCanUseFragCoord = false;
286 static std::unique_ptr<ShaderCaps> CannotUseMinAndAbsTogether() {
287 std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
288 result->fVersionDeclString = "#version 400";
289 result->fCanUseMinAndAbsTogether = false;
293 static std::unique_ptr<ShaderCaps> EmulateAbsIntFunction() {
294 std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
295 result->fVersionDeclString = "#version 400";
296 result->fEmulateAbsIntFunction = true;
300 static std::unique_ptr<ShaderCaps> FramebufferFetchSupport() {
301 std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
302 result->fFBFetchSupport = true;
303 result->fFBFetchColorName = "gl_LastFragData[0]";
307 static std::unique_ptr<ShaderCaps> IncompleteShortIntPrecision() {
308 std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
309 result->fVersionDeclString = "#version 310es";
310 result->fUsesPrecisionModifiers = true;
311 result->fIncompleteShortIntPrecision = true;
315 static std::unique_ptr<ShaderCaps> MustForceNegatedAtanParamToFloat() {
316 std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
317 result->fVersionDeclString = "#version 400";
318 result->fMustForceNegatedAtanParamToFloat = true;
322 static std::unique_ptr<ShaderCaps> MustForceNegatedLdexpParamToMultiply() {
323 std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
324 result->fVersionDeclString = "#version 400";
325 result->fMustForceNegatedLdexpParamToMultiply = true;
329 static std::unique_ptr<ShaderCaps> MustGuardDivisionEvenAfterExplicitZeroCheck() {
330 std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
331 result->fMustGuardDivisionEvenAfterExplicitZeroCheck = true;
335 static std::unique_ptr<ShaderCaps> RemovePowWithConstantExponent() {
336 std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
337 result->fVersionDeclString = "#version 400";
338 result->fRemovePowWithConstantExponent = true;
342 static std::unique_ptr<ShaderCaps> RewriteDoWhileLoops() {
343 std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
344 result->fVersionDeclString = "#version 400";
345 result->fRewriteDoWhileLoops = true;
349 static std::unique_ptr<ShaderCaps> RewriteMatrixComparisons() {
350 std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
351 result->fRewriteMatrixComparisons = true;
352 result->fUsesPrecisionModifiers = true;
356 static std::unique_ptr<ShaderCaps> RewriteMatrixVectorMultiply() {
357 std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
358 result->fVersionDeclString = "#version 400";
359 result->fRewriteMatrixVectorMultiply = true;
363 static std::unique_ptr<ShaderCaps> RewriteSwitchStatements() {
364 std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
365 result->fVersionDeclString = "#version 400";
366 result->fRewriteSwitchStatements = true;
370 static std::unique_ptr<ShaderCaps> SampleMaskSupport() {
371 std::unique_ptr<ShaderCaps> result = Default();
372 result->fSampleMaskSupport = true;
376 static std::unique_ptr<ShaderCaps> ShaderDerivativeExtensionString() {
377 std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
378 result->fVersionDeclString = "#version 400";
379 result->fShaderDerivativeSupport = true;
380 result->fShaderDerivativeExtensionString = "GL_OES_standard_derivatives";
381 result->fUsesPrecisionModifiers = true;
385 static std::unique_ptr<ShaderCaps> UnfoldShortCircuitAsTernary() {
386 std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
387 result->fVersionDeclString = "#version 400";
388 result->fUnfoldShortCircuitAsTernary = true;
392 static std::unique_ptr<ShaderCaps> UsesPrecisionModifiers() {
393 std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
394 result->fVersionDeclString = "#version 400";
395 result->fUsesPrecisionModifiers = true;
399 static std::unique_ptr<ShaderCaps> Version110() {
400 std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
401 result->fVersionDeclString = "#version 110";
402 result->fGLSLGeneration = SkSL::GLSLGeneration::k110;
406 static std::unique_ptr<ShaderCaps> Version450Core() {
407 std::unique_ptr<ShaderCaps> result = MakeShaderCaps();
408 result->fVersionDeclString = "#version 450 core";
413 static std::unique_ptr<ShaderCaps> MakeShaderCaps();
416 #if !defined(SKSL_STANDALONE) && (SK_SUPPORT_GPU || defined(SK_GRAPHITE_ENABLED))
417 bool type_to_sksltype(const Context& context, const Type& type, SkSLType* outType);
420 void write_stringstream(const StringStream& d, OutputStream& out);