Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2012 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #ifndef GrShaderCaps_DEFINED
      9 #define GrShaderCaps_DEFINED
     10 
     11 #include "GrSwizzle.h"
     12 #include "GrTypesPriv.h"
     13 #include "SkRefCnt.h"
     14 #include "glsl/GrGLSL.h"
     15 
     16 namespace SkSL {
     17 class ShaderCapsFactory;
     18 }
     19 
     20 struct GrContextOptions;
     21 class SkJSONWriter;
     22 
     23 class GrShaderCaps : public SkRefCnt {
     24 public:
     25     /**
     26      * Indicates how GLSL must interact with advanced blend equations. The KHR extension requires
     27      * special layout qualifiers in the fragment shader.
     28      */
     29     enum AdvBlendEqInteraction {
     30         kNotSupported_AdvBlendEqInteraction,     //<! No _blend_equation_advanced extension
     31         kAutomatic_AdvBlendEqInteraction,        //<! No interaction required
     32         kGeneralEnable_AdvBlendEqInteraction,    //<! layout(blend_support_all_equations) out
     33         kSpecificEnables_AdvBlendEqInteraction,  //<! Specific layout qualifiers per equation
     34 
     35         kLast_AdvBlendEqInteraction = kSpecificEnables_AdvBlendEqInteraction
     36     };
     37 
     38     GrShaderCaps(const GrContextOptions&);
     39 
     40     void dumpJSON(SkJSONWriter*) const;
     41 
     42     bool supportsDistanceFieldText() const { return fShaderDerivativeSupport; }
     43 
     44     bool shaderDerivativeSupport() const { return fShaderDerivativeSupport; }
     45     bool geometryShaderSupport() const { return fGeometryShaderSupport; }
     46     bool gsInvocationsSupport() const { return fGSInvocationsSupport; }
     47     bool pathRenderingSupport() const { return fPathRenderingSupport; }
     48     bool dstReadInShaderSupport() const { return fDstReadInShaderSupport; }
     49     bool dualSourceBlendingSupport() const { return fDualSourceBlendingSupport; }
     50     bool integerSupport() const { return fIntegerSupport; }
     51     int imageLoadStoreSupport() const { return fImageLoadStoreSupport; }
     52 
     53     /**
     54      * Some helper functions for encapsulating various extensions to read FB Buffer on openglES
     55      *
     56      * TODO(joshualitt) On desktop opengl 4.2+ we can achieve something similar to this effect
     57      */
     58     bool fbFetchSupport() const { return fFBFetchSupport; }
     59 
     60     bool fbFetchNeedsCustomOutput() const { return fFBFetchNeedsCustomOutput; }
     61 
     62     const char* versionDeclString() const { return fVersionDeclString; }
     63 
     64     const char* fbFetchColorName() const { return fFBFetchColorName; }
     65 
     66     const char* fbFetchExtensionString() const { return fFBFetchExtensionString; }
     67 
     68     bool dropsTileOnZeroDivide() const { return fDropsTileOnZeroDivide; }
     69 
     70     bool flatInterpolationSupport() const { return fFlatInterpolationSupport; }
     71 
     72     bool preferFlatInterpolation() const { return fPreferFlatInterpolation; }
     73 
     74     bool noperspectiveInterpolationSupport() const { return fNoPerspectiveInterpolationSupport; }
     75 
     76     bool externalTextureSupport() const { return fExternalTextureSupport; }
     77 
     78     bool vertexIDSupport() const { return fVertexIDSupport; }
     79 
     80     // frexp, ldexp, etc.
     81     bool fpManipulationSupport() const { return fFPManipulationSupport; }
     82 
     83     bool floatIs32Bits() const { return fFloatIs32Bits; }
     84 
     85     bool halfIs32Bits() const { return fHalfIs32Bits; }
     86 
     87     bool unsignedSupport() const { return fUnsignedSupport; }
     88 
     89     // SkSL only.
     90     bool builtinFMASupport() const { return fBuiltinFMASupport; }
     91 
     92     AdvBlendEqInteraction advBlendEqInteraction() const { return fAdvBlendEqInteraction; }
     93 
     94     bool mustEnableAdvBlendEqs() const {
     95         return fAdvBlendEqInteraction >= kGeneralEnable_AdvBlendEqInteraction;
     96     }
     97 
     98     bool mustEnableSpecificAdvBlendEqs() const {
     99         return fAdvBlendEqInteraction == kSpecificEnables_AdvBlendEqInteraction;
    100     }
    101 
    102     bool mustDeclareFragmentShaderOutput() const { return fGLSLGeneration > k110_GrGLSLGeneration; }
    103 
    104     bool usesPrecisionModifiers() const { return fUsesPrecisionModifiers; }
    105 
    106     // Returns whether we can use the glsl function any() in our shader code.
    107     bool canUseAnyFunctionInShader() const { return fCanUseAnyFunctionInShader; }
    108 
    109     bool canUseMinAndAbsTogether() const { return fCanUseMinAndAbsTogether; }
    110 
    111     bool canUseFractForNegativeValues() const { return fCanUseFractForNegativeValues; }
    112 
    113     bool mustForceNegatedAtanParamToFloat() const { return fMustForceNegatedAtanParamToFloat; }
    114 
    115     // Returns whether a device incorrectly implements atan(y,x) as atan(y/x)
    116     bool atan2ImplementedAsAtanYOverX() const { return fAtan2ImplementedAsAtanYOverX; }
    117 
    118     // If this returns true some operation (could be a no op) must be called between floor and abs
    119     // to make sure the driver compiler doesn't inline them together which can cause a driver bug in
    120     // the shader.
    121     bool mustDoOpBetweenFloorAndAbs() const { return fMustDoOpBetweenFloorAndAbs; }
    122 
    123     // If false, SkSL uses a workaround so that sk_FragCoord doesn't actually query gl_FragCoord
    124     bool canUseFragCoord() const { return fCanUseFragCoord; }
    125 
    126     // If true, short ints can't represent every integer in the 16-bit two's complement range as
    127     // required by the spec. SKSL will always emit full ints.
    128     bool incompleteShortIntPrecision() const { return fIncompleteShortIntPrecision; }
    129 
    130     // If true, then conditions in for loops need "&& true" to work around driver bugs.
    131     bool addAndTrueToLoopCondition() const { return fAddAndTrueToLoopCondition; }
    132 
    133     // If true, then expressions such as "x && y" or "x || y" are rewritten as
    134     // ternary to work around driver bugs.
    135     bool unfoldShortCircuitAsTernary() const { return fUnfoldShortCircuitAsTernary; }
    136 
    137     bool emulateAbsIntFunction() const { return fEmulateAbsIntFunction; }
    138 
    139     bool rewriteDoWhileLoops() const { return fRewriteDoWhileLoops; }
    140 
    141     bool removePowWithConstantExponent() const { return fRemovePowWithConstantExponent; }
    142 
    143     bool requiresLocalOutputColorForFBFetch() const { return fRequiresLocalOutputColorForFBFetch; }
    144 
    145     bool mustObfuscateUniformColor() const { return fMustObfuscateUniformColor; }
    146 
    147     // The D3D shader compiler, when targeting PS 3.0 (ie within ANGLE) fails to compile certain
    148     // constructs. See detailed comments in GrGLCaps.cpp.
    149     bool mustGuardDivisionEvenAfterExplicitZeroCheck() const {
    150         return fMustGuardDivisionEvenAfterExplicitZeroCheck;
    151     }
    152 
    153     // Returns the string of an extension that must be enabled in the shader to support
    154     // derivatives. If nullptr is returned then no extension needs to be enabled. Before calling
    155     // this function, the caller should check that shaderDerivativeSupport exists.
    156     const char* shaderDerivativeExtensionString() const {
    157         SkASSERT(this->shaderDerivativeSupport());
    158         return fShaderDerivativeExtensionString;
    159     }
    160 
    161     // Returns the string of an extension that must be enabled in the shader to support geometry
    162     // shaders. If nullptr is returned then no extension needs to be enabled. Before calling this
    163     // function, the caller must verify that geometryShaderSupport exists.
    164     const char* geometryShaderExtensionString() const {
    165         SkASSERT(this->geometryShaderSupport());
    166         return fGeometryShaderExtensionString;
    167     }
    168 
    169     // Returns the string of an extension that must be enabled in the shader to support
    170     // geometry shader invocations. If nullptr is returned then no extension needs to be enabled.
    171     // Before calling this function, the caller must verify that gsInvocationsSupport exists.
    172     const char* gsInvocationsExtensionString() const {
    173         SkASSERT(this->gsInvocationsSupport());
    174         return fGSInvocationsExtensionString;
    175     }
    176 
    177     // Returns the string of an extension that will do all necessary coord transfomations needed
    178     // when reading the fragment position. If such an extension does not exisits, this function
    179     // returns a nullptr, and all transforms of the frag position must be done manually in the
    180     // shader.
    181     const char* fragCoordConventionsExtensionString() const {
    182         return fFragCoordConventionsExtensionString;
    183     }
    184 
    185     // This returns the name of an extension that must be enabled in the shader, if such a thing is
    186     // required in order to use a secondary output in the shader. This returns a nullptr if no such
    187     // extension is required. However, the return value of this function does not say whether dual
    188     // source blending is supported.
    189     const char* secondaryOutputExtensionString() const { return fSecondaryOutputExtensionString; }
    190 
    191     // This returns the name of an extension that must be enabled in the shader to support external
    192     // textures. In some cases, two extensions must be enabled - the second extension is returned
    193     // by secondExternalTextureExtensionString(). If that function returns nullptr, then only one
    194     // extension is required.
    195     const char* externalTextureExtensionString() const {
    196         SkASSERT(this->externalTextureSupport());
    197         return fExternalTextureExtensionString;
    198     }
    199 
    200     const char* secondExternalTextureExtensionString() const {
    201         SkASSERT(this->externalTextureSupport());
    202         return fSecondExternalTextureExtensionString;
    203     }
    204 
    205     const char* noperspectiveInterpolationExtensionString() const {
    206         SkASSERT(this->noperspectiveInterpolationSupport());
    207         return fNoPerspectiveInterpolationExtensionString;
    208     }
    209 
    210     const char* imageLoadStoreExtensionString() const {
    211         SkASSERT(this->imageLoadStoreSupport());
    212         return fImageLoadStoreExtensionString;
    213     }
    214 
    215     int maxFragmentSamplers() const { return fMaxFragmentSamplers; }
    216 
    217     /**
    218      * Given a texture's config, this determines what swizzle must be appended to accesses to the
    219      * texture in generated shader code. Swizzling may be implemented in texture parameters or a
    220      * sampler rather than in the shader. In this case the returned swizzle will always be "rgba".
    221      */
    222     const GrSwizzle& configTextureSwizzle(GrPixelConfig config) const {
    223         return fConfigTextureSwizzle[config];
    224     }
    225 
    226     /** Swizzle that should occur on the fragment shader outputs for a given config. */
    227     const GrSwizzle& configOutputSwizzle(GrPixelConfig config) const {
    228         return fConfigOutputSwizzle[config];
    229     }
    230 
    231     GrGLSLGeneration generation() const { return fGLSLGeneration; }
    232 
    233 private:
    234     void applyOptionsOverrides(const GrContextOptions& options);
    235 
    236     GrGLSLGeneration fGLSLGeneration;
    237 
    238     bool fShaderDerivativeSupport           : 1;
    239     bool fGeometryShaderSupport             : 1;
    240     bool fGSInvocationsSupport              : 1;
    241     bool fPathRenderingSupport              : 1;
    242     bool fDstReadInShaderSupport            : 1;
    243     bool fDualSourceBlendingSupport         : 1;
    244     bool fIntegerSupport                    : 1;
    245     bool fImageLoadStoreSupport             : 1;
    246     bool fDropsTileOnZeroDivide             : 1;
    247     bool fFBFetchSupport                    : 1;
    248     bool fFBFetchNeedsCustomOutput          : 1;
    249     bool fUsesPrecisionModifiers            : 1;
    250     bool fFlatInterpolationSupport          : 1;
    251     bool fPreferFlatInterpolation           : 1;
    252     bool fNoPerspectiveInterpolationSupport : 1;
    253     bool fExternalTextureSupport            : 1;
    254     bool fVertexIDSupport                   : 1;
    255     bool fFPManipulationSupport             : 1;
    256     bool fFloatIs32Bits                     : 1;
    257     bool fHalfIs32Bits                      : 1;
    258     bool fUnsignedSupport                   : 1;
    259 
    260     // Used by SkSL to know when to generate polyfills.
    261     bool fBuiltinFMASupport : 1;
    262 
    263     // Used for specific driver bug work arounds
    264     bool fCanUseAnyFunctionInShader                   : 1;
    265     bool fCanUseMinAndAbsTogether                     : 1;
    266     bool fCanUseFractForNegativeValues                : 1;
    267     bool fMustForceNegatedAtanParamToFloat            : 1;
    268     bool fAtan2ImplementedAsAtanYOverX                : 1;
    269     bool fMustDoOpBetweenFloorAndAbs                  : 1;
    270     bool fRequiresLocalOutputColorForFBFetch          : 1;
    271     bool fMustObfuscateUniformColor                   : 1;
    272     bool fMustGuardDivisionEvenAfterExplicitZeroCheck : 1;
    273     bool fCanUseFragCoord                             : 1;
    274     bool fIncompleteShortIntPrecision                 : 1;
    275     bool fAddAndTrueToLoopCondition                   : 1;
    276     bool fUnfoldShortCircuitAsTernary                 : 1;
    277     bool fEmulateAbsIntFunction                       : 1;
    278     bool fRewriteDoWhileLoops                         : 1;
    279     bool fRemovePowWithConstantExponent               : 1;
    280 
    281     const char* fVersionDeclString;
    282 
    283     const char* fShaderDerivativeExtensionString;
    284     const char* fGeometryShaderExtensionString;
    285     const char* fGSInvocationsExtensionString;
    286     const char* fFragCoordConventionsExtensionString;
    287     const char* fSecondaryOutputExtensionString;
    288     const char* fExternalTextureExtensionString;
    289     const char* fSecondExternalTextureExtensionString;
    290     const char* fNoPerspectiveInterpolationExtensionString;
    291     const char* fImageLoadStoreExtensionString;
    292 
    293     const char* fFBFetchColorName;
    294     const char* fFBFetchExtensionString;
    295 
    296     int fMaxFragmentSamplers;
    297 
    298     size_t fDisableImageMultitexturingDstRectAreaThreshold;
    299 
    300     AdvBlendEqInteraction fAdvBlendEqInteraction;
    301 
    302     GrSwizzle fConfigTextureSwizzle[kGrPixelConfigCnt];
    303     GrSwizzle fConfigOutputSwizzle[kGrPixelConfigCnt];
    304 
    305     friend class GrCaps;  // For initialization.
    306     friend class GrGLCaps;
    307     friend class GrMockCaps;
    308     friend class GrMtlCaps;
    309     friend class GrVkCaps;
    310     friend class SkSL::ShaderCapsFactory;
    311 };
    312 
    313 #endif
    314