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 sampleVariablesSupport() const { return fSampleVariablesSupport; }
     77 
     78     bool externalTextureSupport() const { return fExternalTextureSupport; }
     79 
     80     bool vertexIDSupport() const { return fVertexIDSupport; }
     81 
     82     // frexp, ldexp, etc.
     83     bool fpManipulationSupport() const { return fFPManipulationSupport; }
     84 
     85     bool floatIs32Bits() const { return fFloatIs32Bits; }
     86 
     87     bool halfIs32Bits() const { return fHalfIs32Bits; }
     88 
     89     bool hasLowFragmentPrecision() const { return fHasLowFragmentPrecision; }
     90 
     91     bool unsignedSupport() const { return fUnsignedSupport; }
     92 
     93     // SkSL only.
     94     bool builtinFMASupport() const { return fBuiltinFMASupport; }
     95 
     96     AdvBlendEqInteraction advBlendEqInteraction() const { return fAdvBlendEqInteraction; }
     97 
     98     bool mustEnableAdvBlendEqs() const {
     99         return fAdvBlendEqInteraction >= kGeneralEnable_AdvBlendEqInteraction;
    100     }
    101 
    102     bool mustEnableSpecificAdvBlendEqs() const {
    103         return fAdvBlendEqInteraction == kSpecificEnables_AdvBlendEqInteraction;
    104     }
    105 
    106     bool mustDeclareFragmentShaderOutput() const { return fGLSLGeneration > k110_GrGLSLGeneration; }
    107 
    108     bool usesPrecisionModifiers() const { return fUsesPrecisionModifiers; }
    109 
    110     // Returns whether we can use the glsl function any() in our shader code.
    111     bool canUseAnyFunctionInShader() const { return fCanUseAnyFunctionInShader; }
    112 
    113     bool canUseMinAndAbsTogether() const { return fCanUseMinAndAbsTogether; }
    114 
    115     bool canUseFractForNegativeValues() const { return fCanUseFractForNegativeValues; }
    116 
    117     bool mustForceNegatedAtanParamToFloat() const { return fMustForceNegatedAtanParamToFloat; }
    118 
    119     // Returns whether a device incorrectly implements atan(y,x) as atan(y/x)
    120     bool atan2ImplementedAsAtanYOverX() const { return fAtan2ImplementedAsAtanYOverX; }
    121 
    122     // If this returns true some operation (could be a no op) must be called between floor and abs
    123     // to make sure the driver compiler doesn't inline them together which can cause a driver bug in
    124     // the shader.
    125     bool mustDoOpBetweenFloorAndAbs() const { return fMustDoOpBetweenFloorAndAbs; }
    126 
    127     // If false, SkSL uses a workaround so that sk_FragCoord doesn't actually query gl_FragCoord
    128     bool canUseFragCoord() const { return fCanUseFragCoord; }
    129 
    130     // If true, short ints can't represent every integer in the 16-bit two's complement range as
    131     // required by the spec. SKSL will always emit full ints.
    132     bool incompleteShortIntPrecision() const { return fIncompleteShortIntPrecision; }
    133 
    134     // If true, then conditions in for loops need "&& true" to work around driver bugs.
    135     bool addAndTrueToLoopCondition() const { return fAddAndTrueToLoopCondition; }
    136 
    137     // If true, then expressions such as "x && y" or "x || y" are rewritten as
    138     // ternary to work around driver bugs.
    139     bool unfoldShortCircuitAsTernary() const { return fUnfoldShortCircuitAsTernary; }
    140 
    141     bool emulateAbsIntFunction() const { return fEmulateAbsIntFunction; }
    142 
    143     bool rewriteDoWhileLoops() const { return fRewriteDoWhileLoops; }
    144 
    145     bool removePowWithConstantExponent() const { return fRemovePowWithConstantExponent; }
    146 
    147     bool requiresLocalOutputColorForFBFetch() const { return fRequiresLocalOutputColorForFBFetch; }
    148 
    149     bool mustObfuscateUniformColor() const { return fMustObfuscateUniformColor; }
    150 
    151     // The D3D shader compiler, when targeting PS 3.0 (ie within ANGLE) fails to compile certain
    152     // constructs. See detailed comments in GrGLCaps.cpp.
    153     bool mustGuardDivisionEvenAfterExplicitZeroCheck() const {
    154         return fMustGuardDivisionEvenAfterExplicitZeroCheck;
    155     }
    156 
    157     // Returns the string of an extension that must be enabled in the shader to support
    158     // derivatives. If nullptr is returned then no extension needs to be enabled. Before calling
    159     // this function, the caller should check that shaderDerivativeSupport exists.
    160     const char* shaderDerivativeExtensionString() const {
    161         SkASSERT(this->shaderDerivativeSupport());
    162         return fShaderDerivativeExtensionString;
    163     }
    164 
    165     // Returns the string of an extension that must be enabled in the shader to support geometry
    166     // shaders. If nullptr is returned then no extension needs to be enabled. Before calling this
    167     // function, the caller must verify that geometryShaderSupport exists.
    168     const char* geometryShaderExtensionString() const {
    169         SkASSERT(this->geometryShaderSupport());
    170         return fGeometryShaderExtensionString;
    171     }
    172 
    173     // Returns the string of an extension that must be enabled in the shader to support
    174     // geometry shader invocations. If nullptr is returned then no extension needs to be enabled.
    175     // Before calling this function, the caller must verify that gsInvocationsSupport exists.
    176     const char* gsInvocationsExtensionString() const {
    177         SkASSERT(this->gsInvocationsSupport());
    178         return fGSInvocationsExtensionString;
    179     }
    180 
    181     // Returns the string of an extension that will do all necessary coord transfomations needed
    182     // when reading the fragment position. If such an extension does not exisits, this function
    183     // returns a nullptr, and all transforms of the frag position must be done manually in the
    184     // shader.
    185     const char* fragCoordConventionsExtensionString() const {
    186         return fFragCoordConventionsExtensionString;
    187     }
    188 
    189     // This returns the name of an extension that must be enabled in the shader, if such a thing is
    190     // required in order to use a secondary output in the shader. This returns a nullptr if no such
    191     // extension is required. However, the return value of this function does not say whether dual
    192     // source blending is supported.
    193     const char* secondaryOutputExtensionString() const { return fSecondaryOutputExtensionString; }
    194 
    195     // This returns the name of an extension that must be enabled in the shader to support external
    196     // textures. In some cases, two extensions must be enabled - the second extension is returned
    197     // by secondExternalTextureExtensionString(). If that function returns nullptr, then only one
    198     // extension is required.
    199     const char* externalTextureExtensionString() const {
    200         SkASSERT(this->externalTextureSupport());
    201         return fExternalTextureExtensionString;
    202     }
    203 
    204     const char* secondExternalTextureExtensionString() const {
    205         SkASSERT(this->externalTextureSupport());
    206         return fSecondExternalTextureExtensionString;
    207     }
    208 
    209     const char* noperspectiveInterpolationExtensionString() const {
    210         SkASSERT(this->noperspectiveInterpolationSupport());
    211         return fNoPerspectiveInterpolationExtensionString;
    212     }
    213 
    214     const char* sampleVariablesExtensionString() const {
    215         SkASSERT(this->sampleVariablesSupport());
    216         return fSampleVariablesExtensionString;
    217     }
    218 
    219     const char* imageLoadStoreExtensionString() const {
    220         SkASSERT(this->imageLoadStoreSupport());
    221         return fImageLoadStoreExtensionString;
    222     }
    223 
    224     int maxFragmentSamplers() const { return fMaxFragmentSamplers; }
    225 
    226     /**
    227      * Given a texture's config, this determines what swizzle must be appended to accesses to the
    228      * texture in generated shader code. Swizzling may be implemented in texture parameters or a
    229      * sampler rather than in the shader. In this case the returned swizzle will always be "rgba".
    230      */
    231     const GrSwizzle& configTextureSwizzle(GrPixelConfig config) const {
    232         return fConfigTextureSwizzle[config];
    233     }
    234 
    235     /** Swizzle that should occur on the fragment shader outputs for a given config. */
    236     const GrSwizzle& configOutputSwizzle(GrPixelConfig config) const {
    237         return fConfigOutputSwizzle[config];
    238     }
    239 
    240     GrGLSLGeneration generation() const { return fGLSLGeneration; }
    241 
    242 private:
    243     void applyOptionsOverrides(const GrContextOptions& options);
    244 
    245     GrGLSLGeneration fGLSLGeneration;
    246 
    247     bool fShaderDerivativeSupport           : 1;
    248     bool fGeometryShaderSupport             : 1;
    249     bool fGSInvocationsSupport              : 1;
    250     bool fPathRenderingSupport              : 1;
    251     bool fDstReadInShaderSupport            : 1;
    252     bool fDualSourceBlendingSupport         : 1;
    253     bool fIntegerSupport                    : 1;
    254     bool fImageLoadStoreSupport             : 1;
    255     bool fDropsTileOnZeroDivide             : 1;
    256     bool fFBFetchSupport                    : 1;
    257     bool fFBFetchNeedsCustomOutput          : 1;
    258     bool fUsesPrecisionModifiers            : 1;
    259     bool fFlatInterpolationSupport          : 1;
    260     bool fPreferFlatInterpolation           : 1;
    261     bool fNoPerspectiveInterpolationSupport : 1;
    262     bool fSampleVariablesSupport            : 1;
    263     bool fExternalTextureSupport            : 1;
    264     bool fVertexIDSupport                   : 1;
    265     bool fFPManipulationSupport             : 1;
    266     bool fFloatIs32Bits                     : 1;
    267     bool fHalfIs32Bits                      : 1;
    268     bool fHasLowFragmentPrecision           : 1;
    269     bool fUnsignedSupport                   : 1;
    270 
    271     // Used by SkSL to know when to generate polyfills.
    272     bool fBuiltinFMASupport : 1;
    273 
    274     // Used for specific driver bug work arounds
    275     bool fCanUseAnyFunctionInShader                   : 1;
    276     bool fCanUseMinAndAbsTogether                     : 1;
    277     bool fCanUseFractForNegativeValues                : 1;
    278     bool fMustForceNegatedAtanParamToFloat            : 1;
    279     bool fAtan2ImplementedAsAtanYOverX                : 1;
    280     bool fMustDoOpBetweenFloorAndAbs                  : 1;
    281     bool fRequiresLocalOutputColorForFBFetch          : 1;
    282     bool fMustObfuscateUniformColor                   : 1;
    283     bool fMustGuardDivisionEvenAfterExplicitZeroCheck : 1;
    284     bool fCanUseFragCoord                             : 1;
    285     bool fIncompleteShortIntPrecision                 : 1;
    286     bool fAddAndTrueToLoopCondition                   : 1;
    287     bool fUnfoldShortCircuitAsTernary                 : 1;
    288     bool fEmulateAbsIntFunction                       : 1;
    289     bool fRewriteDoWhileLoops                         : 1;
    290     bool fRemovePowWithConstantExponent               : 1;
    291 
    292     const char* fVersionDeclString;
    293 
    294     const char* fShaderDerivativeExtensionString;
    295     const char* fGeometryShaderExtensionString;
    296     const char* fGSInvocationsExtensionString;
    297     const char* fFragCoordConventionsExtensionString;
    298     const char* fSecondaryOutputExtensionString;
    299     const char* fExternalTextureExtensionString;
    300     const char* fSecondExternalTextureExtensionString;
    301     const char* fNoPerspectiveInterpolationExtensionString;
    302     const char* fSampleVariablesExtensionString;
    303     const char* fImageLoadStoreExtensionString;
    304 
    305     const char* fFBFetchColorName;
    306     const char* fFBFetchExtensionString;
    307 
    308     int fMaxFragmentSamplers;
    309 
    310     AdvBlendEqInteraction fAdvBlendEqInteraction;
    311 
    312     GrSwizzle fConfigTextureSwizzle[kGrPixelConfigCnt];
    313     GrSwizzle fConfigOutputSwizzle[kGrPixelConfigCnt];
    314 
    315     friend class GrCaps;  // For initialization.
    316     friend class GrGLCaps;
    317     friend class GrMockCaps;
    318     friend class GrMtlCaps;
    319     friend class GrVkCaps;
    320     friend class SkSL::ShaderCapsFactory;
    321 };
    322 
    323 #endif
    324