|  | /* | 
|  | * 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 <memory> | 
|  |  | 
|  | 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,     //<! No _blend_equation_advanced extension | 
|  | kAutomatic_AdvBlendEqInteraction,        //<! No interaction required | 
|  | kGeneralEnable_AdvBlendEqInteraction,    //<! layout(blend_support_all_equations) out | 
|  |  | 
|  | kLast_AdvBlendEqInteraction = kGeneralEnable_AdvBlendEqInteraction | 
|  | }; | 
|  |  | 
|  | bool mustEnableAdvBlendEqs() const { | 
|  | return fAdvBlendEqInteraction >= 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; } | 
|  |  | 
|  | /** | 
|  | * The following group of attributes are only needed for Ganesh/GL. However, we keep there here | 
|  | * as opposed to demoting them to being defined in Ganesh's GrShaderCaps for 2 reasons. | 
|  | * | 
|  | * 1) Some backend-agnostic SkSL utilies reference these capabilities. | 
|  | * | 
|  | * 2) Even though we do not anticipate Dawn relying upon Skia's GLSL generation for GL support, | 
|  | *    sometimes SkSL compilation itself can be impacted by some of these capabilities. Such | 
|  | *    attributes will be kept here in case Dawn/GL eventually needs to leverage them. | 
|  | */ | 
|  | bool fFloatIs32Bits = true; /* Queried by SkSLSetting + impacts SkSL generation */ | 
|  | /** | 
|  | * TODO: Modify SkSLGLSLCodeGenerator to use GrShaderCaps rather than this struct since GL | 
|  | * should only be used with Ganesh. Once that is complete, the following attribute could be | 
|  | * downgraded to GrShaderCaps. | 
|  | */ | 
|  | SkSL::GLSLGeneration fGLSLGeneration = SkSL::GLSLGeneration::k330; | 
|  | bool fFlatInterpolationSupport = false; /* Supported by all backends except for some GL impls */ | 
|  | bool fUsesPrecisionModifiers = false; /* GLSL is the only shading language that uses these */ | 
|  |  | 
|  | 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 fNoPerspectiveInterpolationSupport = false; | 
|  | bool fSampleMaskSupport = false; | 
|  | bool fExternalTextureSupport = false; | 
|  |  | 
|  | /** isinf() is defined + 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;  // skbug.com/40043167 | 
|  | /** 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. | 
|  | * (skbug.com/40042841) | 
|  | */ | 
|  | bool fRewriteMatrixVectorMultiply = false; | 
|  | /** Rewrites matrix equality comparisons to avoid an Adreno driver bug. (skbug.com/40042682) */ | 
|  | bool fRewriteMatrixComparisons = false; | 
|  | /** Strips const from function parameters in the GLSL code generator. (skbug.com/40044949) */ | 
|  | 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; | 
|  | /** | 
|  | * Some NVIDIA drivers fail to create a pipeline if RelaxedPrecision is applied to | 
|  | * OpImageSampleImplicitLod when sampling from a YCbCr image. This workaround simply disables | 
|  | * RelaxedPrecision for that op regardless of image kind. (skbug.com/421927604) | 
|  | */ | 
|  | bool fCannotUseRelaxedPrecisionOnImageSample = false; | 
|  | /** | 
|  | * Clamp, Min, Max, intrinsics all appear to be broken on Intel UHD630, so shaders for these | 
|  | * devices will break these intrinsics into individual scalar commands. | 
|  | */ | 
|  | bool fVectorClampMinMaxSupport = true; | 
|  |  | 
|  | 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* const sCaps = [] { | 
|  | std::unique_ptr<ShaderCaps> caps = MakeShaderCaps(); | 
|  | caps->fVersionDeclString = "#version 400"; | 
|  | caps->fShaderDerivativeSupport = true; | 
|  | return caps.release(); | 
|  | }(); | 
|  | return sCaps; | 
|  | } | 
|  |  | 
|  | static const ShaderCaps* Standalone() { | 
|  | static const SkSL::ShaderCaps* const sCaps = MakeShaderCaps().release(); | 
|  | return sCaps; | 
|  | } | 
|  |  | 
|  | protected: | 
|  | static std::unique_ptr<ShaderCaps> 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 |