/* * Copyright 2016 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SKSL_UTIL #define SKSL_UTIL #include "include/core/SkTypes.h" #include "include/sksl/SkSLVersion.h" #include "src/sksl/SkSLGLSL.h" #include enum class SkSLType : char; namespace SkSL { class Context; class OutputStream; class StringStream; class Type; struct ShaderCaps { /** * Indicates how GLSL must interact with advanced blend equations. The KHR extension requires * special layout qualifiers in the fragment shader. */ enum AdvBlendEqInteraction { kNotSupported_AdvBlendEqInteraction, //= kGeneralEnable_AdvBlendEqInteraction; } bool mustDeclareFragmentShaderOutput() const { return fGLSLGeneration > SkSL::GLSLGeneration::k110; } // Returns the string of an extension that must be enabled in the shader to support // derivatives. If nullptr is returned then no extension needs to be enabled. Before calling // this function, the caller should check that shaderDerivativeSupport exists. const char* shaderDerivativeExtensionString() const { SkASSERT(this->fShaderDerivativeSupport); return fShaderDerivativeExtensionString; } // This returns the name of an extension that must be enabled in the shader to support external // textures. In some cases, two extensions must be enabled - the second extension is returned // by secondExternalTextureExtensionString(). If that function returns nullptr, then only one // extension is required. const char* externalTextureExtensionString() const { SkASSERT(this->fExternalTextureSupport); return fExternalTextureExtensionString; } const char* secondExternalTextureExtensionString() const { SkASSERT(this->fExternalTextureSupport); return fSecondExternalTextureExtensionString; } /** * SkSL 300 requires support for derivatives, nonsquare matrices and bitwise integer operations. */ SkSL::Version supportedSkSLVerion() const { if (fShaderDerivativeSupport && fNonsquareMatrixSupport && fIntegerSupport && fGLSLGeneration >= SkSL::GLSLGeneration::k330) { return SkSL::Version::k300; } return SkSL::Version::k100; } bool supportsDistanceFieldText() const { return fShaderDerivativeSupport; } SkSL::GLSLGeneration fGLSLGeneration = SkSL::GLSLGeneration::k330; bool fDualSourceBlendingSupport = false; bool fShaderDerivativeSupport = false; /** Enables sampleGrad and sampleLod functions that don't rely on implicit derivatives */ bool fExplicitTextureLodSupport = false; /** Indicates true 32-bit integer support, with unsigned types and bitwise operations */ bool fIntegerSupport = false; bool fNonsquareMatrixSupport = false; /** asinh(), acosh(), atanh() */ bool fInverseHyperbolicSupport = false; bool fFBFetchSupport = false; bool fFBFetchNeedsCustomOutput = false; bool fUsesPrecisionModifiers = false; bool fFlatInterpolationSupport = false; bool fNoPerspectiveInterpolationSupport = false; bool fSampleMaskSupport = false; bool fExternalTextureSupport = false; bool fFloatIs32Bits = true; // isinf() is defined, and floating point infinities are handled according to IEEE standards. bool fInfinitySupport = false; // Used by SkSL to know when to generate polyfills. bool fBuiltinFMASupport = true; bool fBuiltinDeterminantSupport = true; // Used for specific driver bug work arounds bool fCanUseVoidInSequenceExpressions = true; bool fCanUseMinAndAbsTogether = true; bool fCanUseFractForNegativeValues = true; bool fMustForceNegatedAtanParamToFloat = false; bool fMustForceNegatedLdexpParamToMultiply = false; // http://skbug.com/12076 // Returns whether a device incorrectly implements atan(y,x) as atan(y/x) bool fAtan2ImplementedAsAtanYOverX = false; // If this returns true some operation (could be a no op) must be called between floor and abs // to make sure the driver compiler doesn't inline them together which can cause a driver bug in // the shader. bool fMustDoOpBetweenFloorAndAbs = false; // The D3D shader compiler, when targeting PS 3.0 (ie within ANGLE) fails to compile certain // constructs. See detailed comments in GrGLCaps.cpp. bool fMustGuardDivisionEvenAfterExplicitZeroCheck = false; // If false, SkSL uses a workaround so that sk_FragCoord doesn't actually query gl_FragCoord bool fCanUseFragCoord = true; // If true, then conditions in for loops need "&& true" to work around driver bugs. bool fAddAndTrueToLoopCondition = false; // If true, then expressions such as "x && y" or "x || y" are rewritten as ternary to work // around driver bugs. bool fUnfoldShortCircuitAsTernary = false; bool fEmulateAbsIntFunction = false; bool fRewriteDoWhileLoops = false; bool fRewriteSwitchStatements = false; bool fRemovePowWithConstantExponent = false; // The Android emulator claims samplerExternalOES is an unknown type if a default precision // statement is made for the type. bool fNoDefaultPrecisionForExternalSamplers = false; // ARM GPUs calculate `matrix * vector` in SPIR-V at full precision, even when the inputs are // RelaxedPrecision. Rewriting the multiply as a sum of vector*scalar fixes this. (skia:11769) bool fRewriteMatrixVectorMultiply = false; // Rewrites matrix equality comparisons to avoid an Adreno driver bug. (skia:11308) bool fRewriteMatrixComparisons = false; // Strips const from function parameters in the GLSL code generator. (skia:13858) bool fRemoveConstFromFunctionParameters = false; // On some Android devices colors aren't accurate enough for the double lookup in the // Perlin noise shader. This workaround aggressively snaps colors to multiples of 1/255. bool fPerlinNoiseRoundingFix = false; // Vulkan requires certain builtin variables be present, even if they're unused. At one time, // validation errors would result if sk_Clockwise was missing. Now, it's just (Adreno) driver // bugs that drop or corrupt draws if they're missing. bool fMustDeclareFragmentFrontFacing = false; // SPIR-V currently doesn't handle different array strides being passed in to a fixed sized // array function parameter, so fForceStd430ArrayLayout will make all array strides conform // to std430 stride alignment rules. bool fForceStd430ArrayLayout = false; const char* fVersionDeclString = ""; const char* fShaderDerivativeExtensionString = nullptr; const char* fExternalTextureExtensionString = nullptr; const char* fSecondExternalTextureExtensionString = nullptr; const char* fFBFetchColorName = nullptr; AdvBlendEqInteraction fAdvBlendEqInteraction = kNotSupported_AdvBlendEqInteraction; }; // Various sets of caps for use in tests class ShaderCapsFactory { public: static const ShaderCaps* Default() { static const SkSL::ShaderCaps* sCaps = [] { std::unique_ptr caps = MakeShaderCaps(); caps->fVersionDeclString = "#version 400"; caps->fShaderDerivativeSupport = true; return caps.release(); }(); return sCaps; } static const ShaderCaps* Standalone() { static const SkSL::ShaderCaps* sCaps = MakeShaderCaps().release(); return sCaps; } protected: static std::unique_ptr MakeShaderCaps(); }; bool type_to_sksltype(const Context& context, const Type& type, SkSLType* outType); void write_stringstream(const StringStream& d, OutputStream& out); } // namespace SkSL #endif // SKSL_UTIL