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 
      9 #ifndef GrShaderCaps_DEFINED
     10 #define GrShaderCaps_DEFINED
     11 
     12 #include "../private/GrSwizzle.h"
     13 #include "../private/GrGLSL.h"
     14 
     15 namespace SkSL {
     16     class ShaderCapsFactory;
     17 }
     18 struct GrContextOptions;
     19 
     20 class GrShaderCaps : public SkRefCnt {
     21 public:
     22     /** Info about shader variable precision within a given shader stage. That is, this info
     23         is relevant to a float (or vecNf) variable declared with a GrSLPrecision
     24         in a given GrShaderType. The info here is hoisted from the OpenGL spec. */
     25     struct PrecisionInfo {
     26         PrecisionInfo() {
     27             fLogRangeLow = 0;
     28             fLogRangeHigh = 0;
     29             fBits = 0;
     30         }
     31 
     32         /** Is this precision level allowed in the shader stage? */
     33         bool supported() const { return 0 != fBits; }
     34 
     35         bool operator==(const PrecisionInfo& that) const {
     36             return fLogRangeLow == that.fLogRangeLow && fLogRangeHigh == that.fLogRangeHigh &&
     37                    fBits == that.fBits;
     38         }
     39         bool operator!=(const PrecisionInfo& that) const { return !(*this == that); }
     40 
     41         /** floor(log2(|min_value|)) */
     42         int fLogRangeLow;
     43         /** floor(log2(|max_value|)) */
     44         int fLogRangeHigh;
     45         /** Number of bits of precision. As defined in OpenGL (with names modified to reflect this
     46             struct) :
     47             """
     48             If the smallest representable value greater than 1 is 1 + e, then fBits will
     49             contain floor(log2(e)), and every value in the range [2^fLogRangeLow,
     50             2^fLogRangeHigh] can be represented to at least one part in 2^fBits.
     51             """
     52           */
     53         int fBits;
     54     };
     55 
     56     /**
     57     * Indicates how GLSL must interact with advanced blend equations. The KHR extension requires
     58     * special layout qualifiers in the fragment shader.
     59     */
     60     enum AdvBlendEqInteraction {
     61         kNotSupported_AdvBlendEqInteraction,     //<! No _blend_equation_advanced extension
     62         kAutomatic_AdvBlendEqInteraction,        //<! No interaction required
     63         kGeneralEnable_AdvBlendEqInteraction,    //<! layout(blend_support_all_equations) out
     64         kSpecificEnables_AdvBlendEqInteraction,  //<! Specific layout qualifiers per equation
     65 
     66         kLast_AdvBlendEqInteraction = kSpecificEnables_AdvBlendEqInteraction
     67     };
     68 
     69     GrShaderCaps(const GrContextOptions&);
     70 
     71     SkString dump() const;
     72 
     73     bool shaderDerivativeSupport() const { return fShaderDerivativeSupport; }
     74     bool geometryShaderSupport() const { return fGeometryShaderSupport; }
     75     bool pathRenderingSupport() const { return fPathRenderingSupport; }
     76     bool dstReadInShaderSupport() const { return fDstReadInShaderSupport; }
     77     bool dualSourceBlendingSupport() const { return fDualSourceBlendingSupport; }
     78     bool integerSupport() const { return fIntegerSupport; }
     79     bool texelBufferSupport() const { return fTexelBufferSupport; }
     80     int imageLoadStoreSupport() const { return fImageLoadStoreSupport; }
     81 
     82     /**
     83     * Get the precision info for a variable of type kFloat_GrSLType, kVec2f_GrSLType, etc in a
     84     * given shader type. If the shader type is not supported or the precision level is not
     85     * supported in that shader type then the returned struct will report false when supported() is
     86     * called.
     87     */
     88     const PrecisionInfo& getFloatShaderPrecisionInfo(GrShaderType shaderType,
     89                                                      GrSLPrecision precision) const {
     90         return fFloatPrecisions[shaderType][precision];
     91     }
     92 
     93     /**
     94     * Is there any difference between the float shader variable precision types? If this is true
     95     * then unless the shader type is not supported, any call to getFloatShaderPrecisionInfo() would
     96     * report the same info for all precisions in all shader types.
     97     */
     98     bool floatPrecisionVaries() const { return fShaderPrecisionVaries; }
     99 
    100     /**
    101      * Some helper functions for encapsulating various extensions to read FB Buffer on openglES
    102      *
    103      * TODO(joshualitt) On desktop opengl 4.2+ we can achieve something similar to this effect
    104      */
    105     bool fbFetchSupport() const { return fFBFetchSupport; }
    106 
    107     bool fbFetchNeedsCustomOutput() const { return fFBFetchNeedsCustomOutput; }
    108 
    109     bool bindlessTextureSupport() const { return fBindlessTextureSupport; }
    110 
    111     const char* versionDeclString() const { return fVersionDeclString; }
    112 
    113     const char* fbFetchColorName() const { return fFBFetchColorName; }
    114 
    115     const char* fbFetchExtensionString() const { return fFBFetchExtensionString; }
    116 
    117     bool dropsTileOnZeroDivide() const { return fDropsTileOnZeroDivide; }
    118 
    119     bool flatInterpolationSupport() const { return fFlatInterpolationSupport; }
    120 
    121     bool noperspectiveInterpolationSupport() const { return fNoPerspectiveInterpolationSupport; }
    122 
    123     bool multisampleInterpolationSupport() const { return fMultisampleInterpolationSupport; }
    124 
    125     bool sampleVariablesSupport() const { return fSampleVariablesSupport; }
    126 
    127     bool sampleMaskOverrideCoverageSupport() const { return fSampleMaskOverrideCoverageSupport; }
    128 
    129     bool externalTextureSupport() const { return fExternalTextureSupport; }
    130 
    131     bool texelFetchSupport() const { return fTexelFetchSupport; }
    132 
    133     bool vertexIDSupport() const { return fVertexIDSupport; }
    134 
    135     AdvBlendEqInteraction advBlendEqInteraction() const { return fAdvBlendEqInteraction; }
    136 
    137     bool mustEnableAdvBlendEqs() const {
    138         return fAdvBlendEqInteraction >= kGeneralEnable_AdvBlendEqInteraction;
    139     }
    140 
    141     bool mustEnableSpecificAdvBlendEqs() const {
    142         return fAdvBlendEqInteraction == kSpecificEnables_AdvBlendEqInteraction;
    143     }
    144 
    145     bool mustDeclareFragmentShaderOutput() const {
    146         return fGLSLGeneration > k110_GrGLSLGeneration;
    147     }
    148 
    149     bool usesPrecisionModifiers() const { return fUsesPrecisionModifiers; }
    150 
    151     // Returns whether we can use the glsl function any() in our shader code.
    152     bool canUseAnyFunctionInShader() const { return fCanUseAnyFunctionInShader; }
    153 
    154     bool canUseMinAndAbsTogether() const { return fCanUseMinAndAbsTogether; }
    155 
    156     bool mustForceNegatedAtanParamToFloat() const { return fMustForceNegatedAtanParamToFloat; }
    157 
    158     // Returns whether a device incorrectly implements atan(y,x) as atan(y/x)
    159     bool atan2ImplementedAsAtanYOverX() const { return fAtan2ImplementedAsAtanYOverX; }
    160 
    161     bool requiresLocalOutputColorForFBFetch() const { return fRequiresLocalOutputColorForFBFetch; }
    162 
    163     // On MacBook, geometry shaders break if they have more than one invocation.
    164     bool mustImplementGSInvocationsWithLoop() const { return fMustImplementGSInvocationsWithLoop; }
    165 
    166     bool mustObfuscateUniformColor() const { return fMustObfuscateUniformColor; }
    167 
    168     // Returns the string of an extension that must be enabled in the shader to support
    169     // derivatives. If nullptr is returned then no extension needs to be enabled. Before calling
    170     // this function, the caller should check that shaderDerivativeSupport exists.
    171     const char* shaderDerivativeExtensionString() const {
    172         SkASSERT(this->shaderDerivativeSupport());
    173         return fShaderDerivativeExtensionString;
    174     }
    175 
    176     // Returns the string of an extension that will do all necessary coord transfomations needed
    177     // when reading the fragment position. If such an extension does not exisits, this function
    178     // returns a nullptr, and all transforms of the frag position must be done manually in the
    179     // shader.
    180     const char* fragCoordConventionsExtensionString() const {
    181         return fFragCoordConventionsExtensionString;
    182     }
    183 
    184     // This returns the name of an extension that must be enabled in the shader, if such a thing is
    185     // required in order to use a secondary output in the shader. This returns a nullptr if no such
    186     // extension is required. However, the return value of this function does not say whether dual
    187     // source blending is supported.
    188     const char* secondaryOutputExtensionString() const {
    189         return fSecondaryOutputExtensionString;
    190     }
    191 
    192     const char* externalTextureExtensionString() const {
    193         SkASSERT(this->externalTextureSupport());
    194         return fExternalTextureExtensionString;
    195     }
    196 
    197     const char* texelBufferExtensionString() const {
    198         SkASSERT(this->texelBufferSupport());
    199         return fTexelBufferExtensionString;
    200     }
    201 
    202     const char* noperspectiveInterpolationExtensionString() const {
    203         SkASSERT(this->noperspectiveInterpolationSupport());
    204         return fNoPerspectiveInterpolationExtensionString;
    205     }
    206 
    207     const char* multisampleInterpolationExtensionString() const {
    208         SkASSERT(this->multisampleInterpolationSupport());
    209         return fMultisampleInterpolationExtensionString;
    210     }
    211 
    212     const char* sampleVariablesExtensionString() const {
    213         SkASSERT(this->sampleVariablesSupport());
    214         return fSampleVariablesExtensionString;
    215     }
    216 
    217     const char* imageLoadStoreExtensionString() const {
    218         SkASSERT(this->imageLoadStoreSupport());
    219         return fImageLoadStoreExtensionString;
    220     }
    221 
    222     int maxVertexSamplers() const { return fMaxVertexSamplers; }
    223 
    224     int maxGeometrySamplers() const { return fMaxGeometrySamplers; }
    225 
    226     int maxFragmentSamplers() const { return fMaxFragmentSamplers; }
    227 
    228     int maxCombinedSamplers() const { return fMaxCombinedSamplers; }
    229 
    230     int maxVertexImageStorages() const { return fMaxVertexImageStorages; }
    231 
    232     int maxGeometryImageStorages() const { return fMaxGeometryImageStorages; }
    233 
    234     int maxFragmentImageStorages() const { return fMaxFragmentImageStorages; }
    235 
    236     int maxCombinedImageStorages() const { return fMaxCombinedImageStorages; }
    237 
    238     /**
    239      * Given a texture's config, this determines what swizzle must be appended to accesses to the
    240      * texture in generated shader code. Swizzling may be implemented in texture parameters or a
    241      * sampler rather than in the shader. In this case the returned swizzle will always be "rgba".
    242      */
    243     const GrSwizzle& configTextureSwizzle(GrPixelConfig config) const {
    244         return fConfigTextureSwizzle[config];
    245     }
    246 
    247     /** Swizzle that should occur on the fragment shader outputs for a given config. */
    248     const GrSwizzle& configOutputSwizzle(GrPixelConfig config) const {
    249         return fConfigOutputSwizzle[config];
    250     }
    251 
    252     /** Precision qualifier that should be used with a sampler, given its config and visibility. */
    253     GrSLPrecision samplerPrecision(GrPixelConfig config, GrShaderFlags visibility) const {
    254         return static_cast<GrSLPrecision>(fSamplerPrecisions[visibility][config]);
    255     }
    256 
    257     GrGLSLGeneration generation() const { return fGLSLGeneration; }
    258 
    259 private:
    260     /** GrCaps subclasses must call this after filling in the shader precision table. */
    261     void initSamplerPrecisionTable();
    262 
    263     void applyOptionsOverrides(const GrContextOptions& options);
    264 
    265     GrGLSLGeneration fGLSLGeneration;
    266 
    267     bool fShaderDerivativeSupport   : 1;
    268     bool fGeometryShaderSupport     : 1;
    269     bool fPathRenderingSupport      : 1;
    270     bool fDstReadInShaderSupport    : 1;
    271     bool fDualSourceBlendingSupport : 1;
    272     bool fIntegerSupport            : 1;
    273     bool fTexelBufferSupport        : 1;
    274     bool fImageLoadStoreSupport     : 1;
    275     bool fShaderPrecisionVaries     : 1;
    276     bool fDropsTileOnZeroDivide : 1;
    277     bool fFBFetchSupport : 1;
    278     bool fFBFetchNeedsCustomOutput : 1;
    279     bool fBindlessTextureSupport : 1;
    280     bool fUsesPrecisionModifiers : 1;
    281     bool fCanUseAnyFunctionInShader : 1;
    282     bool fFlatInterpolationSupport : 1;
    283     bool fNoPerspectiveInterpolationSupport : 1;
    284     bool fMultisampleInterpolationSupport : 1;
    285     bool fSampleVariablesSupport : 1;
    286     bool fSampleMaskOverrideCoverageSupport : 1;
    287     bool fExternalTextureSupport : 1;
    288     bool fTexelFetchSupport : 1;
    289     bool fVertexIDSupport : 1;
    290 
    291     // Used for specific driver bug work arounds
    292     bool fCanUseMinAndAbsTogether : 1;
    293     bool fMustForceNegatedAtanParamToFloat : 1;
    294     bool fAtan2ImplementedAsAtanYOverX : 1;
    295     bool fRequiresLocalOutputColorForFBFetch : 1;
    296     bool fMustImplementGSInvocationsWithLoop : 1;
    297     bool fMustObfuscateUniformColor : 1;
    298 
    299     PrecisionInfo fFloatPrecisions[kGrShaderTypeCount][kGrSLPrecisionCount];
    300 
    301     const char* fVersionDeclString;
    302 
    303     const char* fShaderDerivativeExtensionString;
    304     const char* fFragCoordConventionsExtensionString;
    305     const char* fSecondaryOutputExtensionString;
    306     const char* fExternalTextureExtensionString;
    307     const char* fTexelBufferExtensionString;
    308     const char* fNoPerspectiveInterpolationExtensionString;
    309     const char* fMultisampleInterpolationExtensionString;
    310     const char* fSampleVariablesExtensionString;
    311     const char* fImageLoadStoreExtensionString;
    312 
    313     const char* fFBFetchColorName;
    314     const char* fFBFetchExtensionString;
    315 
    316     int fMaxVertexSamplers;
    317     int fMaxGeometrySamplers;
    318     int fMaxFragmentSamplers;
    319     int fMaxCombinedSamplers;
    320 
    321     int fMaxVertexImageStorages;
    322     int fMaxGeometryImageStorages;
    323     int fMaxFragmentImageStorages;
    324     int fMaxCombinedImageStorages;
    325 
    326     AdvBlendEqInteraction fAdvBlendEqInteraction;
    327 
    328     GrSwizzle fConfigTextureSwizzle[kGrPixelConfigCnt];
    329     GrSwizzle fConfigOutputSwizzle[kGrPixelConfigCnt];
    330 
    331     uint8_t fSamplerPrecisions[(1 << kGrShaderTypeCount)][kGrPixelConfigCnt];
    332 
    333     friend class GrGLCaps;  // For initialization.
    334     friend class GrVkCaps;
    335     friend class SkSL::ShaderCapsFactory;
    336 };
    337 
    338 #endif
    339