/* * 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 #include "stdlib.h" #include "string.h" #include "src/sksl/SkSLDefines.h" #include "src/sksl/SkSLLexer.h" #ifndef SKSL_STANDALONE #include "include/core/SkTypes.h" #include "include/private/GrTypesPriv.h" #if SK_SUPPORT_GPU #include "include/gpu/GrContextOptions.h" #include "src/gpu/GrShaderCaps.h" #endif // SK_SUPPORT_GPU #endif // SKSL_STANDALONE class GrShaderCaps; namespace SkSL { class Context; class OutputStream; class StringStream; class Type; #if defined(SKSL_STANDALONE) || !SK_SUPPORT_GPU // we're being compiled standalone, so we don't have access to caps... enum GrGLSLGeneration { k110_GrGLSLGeneration, k130_GrGLSLGeneration, k140_GrGLSLGeneration, k150_GrGLSLGeneration, k330_GrGLSLGeneration, k400_GrGLSLGeneration, k420_GrGLSLGeneration, k310es_GrGLSLGeneration, k320es_GrGLSLGeneration, }; class StandaloneShaderCaps { public: GrGLSLGeneration fGLSLGeneration = k400_GrGLSLGeneration; GrGLSLGeneration generation() const { return fGLSLGeneration; } bool fAtan2ImplementedAsAtanYOverX = false; bool atan2ImplementedAsAtanYOverX() const { return fAtan2ImplementedAsAtanYOverX; } bool fCanUseMinAndAbsTogether = true; bool canUseMinAndAbsTogether() const { return fCanUseMinAndAbsTogether; } bool fMustForceNegatedAtanParamToFloat = false; bool mustForceNegatedAtanParamToFloat() const { return fMustForceNegatedAtanParamToFloat; } bool fGeometryShaderSupport = true; bool geometryShaderSupport() const { return fGeometryShaderSupport; } bool fShaderDerivativeSupport = true; bool shaderDerivativeSupport() const { return fShaderDerivativeSupport; } bool fUsesPrecisionModifiers = false; bool usesPrecisionModifiers() const { return fUsesPrecisionModifiers; } bool mustDeclareFragmentShaderOutput() const { return fGLSLGeneration > k110_GrGLSLGeneration; } bool fFBFetchSupport = true; bool fbFetchSupport() const { return fFBFetchSupport; } bool fFBFetchNeedsCustomOutput = false; bool fbFetchNeedsCustomOutput() const { return fFBFetchNeedsCustomOutput; } bool fFlatInterpolationSupport = true; bool flatInterpolationSupport() const { return fFlatInterpolationSupport; } bool fNoperspectiveInterpolationSupport = true; bool noperspectiveInterpolationSupport() const { return fNoperspectiveInterpolationSupport; } bool fMultisampleInterpolationSupport = true; bool multisampleInterpolationSupport() const { return fMultisampleInterpolationSupport; } bool fSampleMaskSupport = true; bool sampleMaskSupport() const { return fSampleMaskSupport; } bool fExternalTextureSupport = true; bool externalTextureSupport() const { return fExternalTextureSupport; } bool fMustDoOpBetweenFloorAndAbs = false; bool mustDoOpBetweenFloorAndAbs() const { return fMustDoOpBetweenFloorAndAbs; } bool fMustGuardDivisionEvenAfterExplicitZeroCheck = false; bool mustGuardDivisionEvenAfterExplicitZeroCheck() const { return fMustGuardDivisionEvenAfterExplicitZeroCheck; } bool fInBlendModesFailRandomlyForAllZeroVec = false; bool inBlendModesFailRandomlyForAllZeroVec() const { return fInBlendModesFailRandomlyForAllZeroVec; } bool fMustEnableAdvBlendEqs = false; bool mustEnableAdvBlendEqs() const { return fMustEnableAdvBlendEqs; } bool fMustEnableSpecificAdvBlendEqs = false; bool mustEnableSpecificAdvBlendEqs() const { return fMustEnableSpecificAdvBlendEqs; } bool fCanUseAnyFunctionInShader = true; bool canUseAnyFunctionInShader() const { return fCanUseAnyFunctionInShader; } bool fNoDefaultPrecisionForExternalSamplers = false; bool noDefaultPrecisionForExternalSamplers() const { return fNoDefaultPrecisionForExternalSamplers; } bool fFloatIs32Bits = true; bool floatIs32Bits() const { return fFloatIs32Bits; } bool fIntegerSupport = false; bool integerSupport() const { return fIntegerSupport; } bool fBuiltinFMASupport = false; bool builtinFMASupport() const { return fBuiltinFMASupport; } bool fBuiltinDeterminantSupport = false; bool builtinDeterminantSupport() const { return fBuiltinDeterminantSupport; } bool fCanUseDoLoops = false; bool canUseDoLoops() const { // we define this to false in standalone so we don't use do loops while inlining in FP files // (which would then, being baked in, end up being used even in contexts where do loops are // not allowed) return fCanUseDoLoops; } const char* fShaderDerivativeExtensionString = nullptr; const char* shaderDerivativeExtensionString() const { return fShaderDerivativeExtensionString; } const char* fFragCoordConventionsExtensionString = nullptr; const char* fragCoordConventionsExtensionString() const { return fFragCoordConventionsExtensionString; } const char* fGeometryShaderExtensionString = nullptr; const char* geometryShaderExtensionString() const { return fGeometryShaderExtensionString; } const char* fGSInvocationsExtensionString = nullptr; const char* gsInvocationsExtensionString() const { return fGSInvocationsExtensionString; } const char* fExternalTextureExtensionString = nullptr; const char* externalTextureExtensionString() const { return fExternalTextureExtensionString; } const char* fSecondExternalTextureExtensionString = nullptr; const char* secondExternalTextureExtensionString() const { return fSecondExternalTextureExtensionString; } const char* fVersionDeclString = ""; const char* versionDeclString() const { return fVersionDeclString; } bool fGSInvocationsSupport = true; bool gsInvocationsSupport() const { return fGSInvocationsSupport; } bool fCanUseFractForNegativeValues = true; bool canUseFractForNegativeValues() const { return fCanUseFractForNegativeValues; } bool fCanUseFragCoord = true; bool canUseFragCoord() const { return fCanUseFragCoord; } bool fIncompleteShortIntPrecision = false; bool incompleteShortIntPrecision() const { return fIncompleteShortIntPrecision; } bool fAddAndTrueToLoopCondition = false; bool addAndTrueToLoopCondition() const { return fAddAndTrueToLoopCondition; } bool fUnfoldShortCircuitAsTernary = false; bool unfoldShortCircuitAsTernary() const { return fUnfoldShortCircuitAsTernary; } bool fEmulateAbsIntFunction = false; bool emulateAbsIntFunction() const { return fEmulateAbsIntFunction; } bool fRewriteDoWhileLoops = false; bool rewriteDoWhileLoops() const { return fRewriteDoWhileLoops; } bool fRemovePowWithConstantExponent = false; bool removePowWithConstantExponent() const { return fRemovePowWithConstantExponent; } const char* fFBFetchColorName = nullptr; const char* fbFetchColorName() const { return fFBFetchColorName; } }; using ShaderCapsClass = StandaloneShaderCaps; using ShaderCapsPointer = std::shared_ptr; extern StandaloneShaderCaps standaloneCaps; #else using ShaderCapsClass = GrShaderCaps; using ShaderCapsPointer = sk_sp; #endif // defined(SKSL_STANDALONE) || !SK_SUPPORT_GPU // Various sets of caps for use in tests class ShaderCapsFactory { public: static ShaderCapsPointer Default() { ShaderCapsPointer result = MakeShaderCaps(); result->fVersionDeclString = "#version 400"; result->fShaderDerivativeSupport = true; result->fBuiltinDeterminantSupport = true; result->fCanUseDoLoops = true; return result; } static ShaderCapsPointer Standalone() { return MakeShaderCaps(); } static ShaderCapsPointer AddAndTrueToLoopCondition() { ShaderCapsPointer result = MakeShaderCaps(); result->fVersionDeclString = "#version 400"; result->fAddAndTrueToLoopCondition = true; return result; } static ShaderCapsPointer BlendModesFailRandomlyForAllZeroVec() { ShaderCapsPointer result = MakeShaderCaps(); result->fInBlendModesFailRandomlyForAllZeroVec = true; return result; } static ShaderCapsPointer CannotUseFractForNegativeValues() { ShaderCapsPointer result = MakeShaderCaps(); result->fVersionDeclString = "#version 400"; result->fCanUseFractForNegativeValues = false; return result; } static ShaderCapsPointer CannotUseFragCoord() { ShaderCapsPointer result = MakeShaderCaps(); result->fVersionDeclString = "#version 400"; result->fCanUseFragCoord = false; return result; } static ShaderCapsPointer CannotUseMinAndAbsTogether() { ShaderCapsPointer result = MakeShaderCaps(); result->fVersionDeclString = "#version 400"; result->fCanUseMinAndAbsTogether = false; return result; } static ShaderCapsPointer EmulateAbsIntFunction() { ShaderCapsPointer result = MakeShaderCaps(); result->fVersionDeclString = "#version 400"; result->fEmulateAbsIntFunction = true; return result; } static ShaderCapsPointer FragCoordsNew() { ShaderCapsPointer result = MakeShaderCaps(); result->fVersionDeclString = "#version 400"; result->fFragCoordConventionsExtensionString = "GL_ARB_fragment_coord_conventions"; return result; } static ShaderCapsPointer FragCoordsOld() { ShaderCapsPointer result = MakeShaderCaps(); result->fVersionDeclString = "#version 110"; result->fGLSLGeneration = GrGLSLGeneration::k110_GrGLSLGeneration; result->fFragCoordConventionsExtensionString = "GL_ARB_fragment_coord_conventions"; return result; } static ShaderCapsPointer GeometryShaderExtensionString() { ShaderCapsPointer result = MakeShaderCaps(); result->fVersionDeclString = "#version 310es"; result->fGeometryShaderSupport = true; result->fGeometryShaderExtensionString = "GL_EXT_geometry_shader"; result->fGSInvocationsSupport = true; return result; } static ShaderCapsPointer GeometryShaderSupport() { ShaderCapsPointer result = MakeShaderCaps(); result->fVersionDeclString = "#version 400"; result->fGeometryShaderSupport = true; result->fGSInvocationsSupport = true; return result; } static ShaderCapsPointer GSInvocationsExtensionString() { ShaderCapsPointer result = MakeShaderCaps(); result->fVersionDeclString = "#version 400"; result->fGeometryShaderSupport = true; result->fGSInvocationsSupport = true; result->fGSInvocationsExtensionString = "GL_ARB_gpu_shader5"; return result; } static ShaderCapsPointer IncompleteShortIntPrecision() { ShaderCapsPointer result = MakeShaderCaps(); result->fVersionDeclString = "#version 310es"; result->fUsesPrecisionModifiers = true; result->fIncompleteShortIntPrecision = true; return result; } static ShaderCapsPointer MustForceNegatedAtanParamToFloat() { ShaderCapsPointer result = MakeShaderCaps(); result->fVersionDeclString = "#version 400"; result->fMustForceNegatedAtanParamToFloat = true; return result; } static ShaderCapsPointer MustGuardDivisionEvenAfterExplicitZeroCheck() { ShaderCapsPointer result = MakeShaderCaps(); result->fMustGuardDivisionEvenAfterExplicitZeroCheck = true; return result; } static ShaderCapsPointer NoGSInvocationsSupport() { ShaderCapsPointer result = MakeShaderCaps(); result->fVersionDeclString = "#version 400"; result->fGeometryShaderSupport = true; result->fGSInvocationsSupport = false; return result; } static ShaderCapsPointer RemovePowWithConstantExponent() { ShaderCapsPointer result = MakeShaderCaps(); result->fVersionDeclString = "#version 400"; result->fRemovePowWithConstantExponent = true; return result; } static ShaderCapsPointer RewriteDoWhileLoops() { ShaderCapsPointer result = MakeShaderCaps(); result->fVersionDeclString = "#version 400"; result->fRewriteDoWhileLoops = true; return result; } static ShaderCapsPointer SampleMaskSupport() { ShaderCapsPointer result = Default(); result->fSampleMaskSupport = true; return result; } static ShaderCapsPointer ShaderDerivativeExtensionString() { ShaderCapsPointer result = MakeShaderCaps(); result->fVersionDeclString = "#version 400"; result->fShaderDerivativeSupport = true; result->fShaderDerivativeExtensionString = "GL_OES_standard_derivatives"; result->fUsesPrecisionModifiers = true; return result; } static ShaderCapsPointer UnfoldShortCircuitAsTernary() { ShaderCapsPointer result = MakeShaderCaps(); result->fVersionDeclString = "#version 400"; result->fUnfoldShortCircuitAsTernary = true; return result; } static ShaderCapsPointer UsesPrecisionModifiers() { ShaderCapsPointer result = MakeShaderCaps(); result->fVersionDeclString = "#version 400"; result->fUsesPrecisionModifiers = true; return result; } static ShaderCapsPointer Version110() { ShaderCapsPointer result = MakeShaderCaps(); result->fVersionDeclString = "#version 110"; result->fGLSLGeneration = GrGLSLGeneration::k110_GrGLSLGeneration; return result; } static ShaderCapsPointer Version450Core() { ShaderCapsPointer result = MakeShaderCaps(); result->fVersionDeclString = "#version 450 core"; return result; } private: static ShaderCapsPointer MakeShaderCaps(); }; #if !defined(SKSL_STANDALONE) bool type_to_grsltype(const Context& context, const Type& type, GrSLType* outType); #endif void write_stringstream(const StringStream& d, OutputStream& out); NORETURN void sksl_abort(); } // namespace SkSL #endif // SKSL_UTIL