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     AdvBlendEqInteraction advBlendEqInteraction() const { return fAdvBlendEqInteraction; }
    134 
    135     bool mustEnableAdvBlendEqs() const {
    136         return fAdvBlendEqInteraction >= kGeneralEnable_AdvBlendEqInteraction;
    137     }
    138 
    139     bool mustEnableSpecificAdvBlendEqs() const {
    140         return fAdvBlendEqInteraction == kSpecificEnables_AdvBlendEqInteraction;
    141     }
    142 
    143     bool mustDeclareFragmentShaderOutput() const {
    144         return fGLSLGeneration > k110_GrGLSLGeneration;
    145     }
    146 
    147     bool usesPrecisionModifiers() const { return fUsesPrecisionModifiers; }
    148 
    149     // Returns whether we can use the glsl function any() in our shader code.
    150     bool canUseAnyFunctionInShader() const { return fCanUseAnyFunctionInShader; }
    151 
    152     bool canUseMinAndAbsTogether() const { return fCanUseMinAndAbsTogether; }
    153 
    154     bool mustForceNegatedAtanParamToFloat() const { return fMustForceNegatedAtanParamToFloat; }
    155 
    156     // Returns whether a device incorrectly implements atan(y,x) as atan(y/x)
    157     bool atan2ImplementedAsAtanYOverX() const { return fAtan2ImplementedAsAtanYOverX; }
    158 
    159     bool requiresLocalOutputColorForFBFetch() const { return fRequiresLocalOutputColorForFBFetch; }
    160 
    161     // On MacBook, geometry shaders break if they have more than one invocation.
    162     bool mustImplementGSInvocationsWithLoop() const { return fMustImplementGSInvocationsWithLoop; }
    163 
    164     // Returns the string of an extension that must be enabled in the shader to support
    165     // derivatives. If nullptr is returned then no extension needs to be enabled. Before calling
    166     // this function, the caller should check that shaderDerivativeSupport exists.
    167     const char* shaderDerivativeExtensionString() const {
    168         SkASSERT(this->shaderDerivativeSupport());
    169         return fShaderDerivativeExtensionString;
    170     }
    171 
    172     // Returns the string of an extension that will do all necessary coord transfomations needed
    173     // when reading the fragment position. If such an extension does not exisits, this function
    174     // returns a nullptr, and all transforms of the frag position must be done manually in the
    175     // shader.
    176     const char* fragCoordConventionsExtensionString() const {
    177         return fFragCoordConventionsExtensionString;
    178     }
    179 
    180     // This returns the name of an extension that must be enabled in the shader, if such a thing is
    181     // required in order to use a secondary output in the shader. This returns a nullptr if no such
    182     // extension is required. However, the return value of this function does not say whether dual
    183     // source blending is supported.
    184     const char* secondaryOutputExtensionString() const {
    185         return fSecondaryOutputExtensionString;
    186     }
    187 
    188     const char* externalTextureExtensionString() const {
    189         SkASSERT(this->externalTextureSupport());
    190         return fExternalTextureExtensionString;
    191     }
    192 
    193     const char* texelBufferExtensionString() const {
    194         SkASSERT(this->texelBufferSupport());
    195         return fTexelBufferExtensionString;
    196     }
    197 
    198     const char* noperspectiveInterpolationExtensionString() const {
    199         SkASSERT(this->noperspectiveInterpolationSupport());
    200         return fNoPerspectiveInterpolationExtensionString;
    201     }
    202 
    203     const char* multisampleInterpolationExtensionString() const {
    204         SkASSERT(this->multisampleInterpolationSupport());
    205         return fMultisampleInterpolationExtensionString;
    206     }
    207 
    208     const char* sampleVariablesExtensionString() const {
    209         SkASSERT(this->sampleVariablesSupport());
    210         return fSampleVariablesExtensionString;
    211     }
    212 
    213     const char* imageLoadStoreExtensionString() const {
    214         SkASSERT(this->imageLoadStoreSupport());
    215         return fImageLoadStoreExtensionString;
    216     }
    217 
    218     int maxVertexSamplers() const { return fMaxVertexSamplers; }
    219 
    220     int maxGeometrySamplers() const { return fMaxGeometrySamplers; }
    221 
    222     int maxFragmentSamplers() const { return fMaxFragmentSamplers; }
    223 
    224     int maxCombinedSamplers() const { return fMaxCombinedSamplers; }
    225 
    226     int maxVertexImageStorages() const { return fMaxVertexImageStorages; }
    227 
    228     int maxGeometryImageStorages() const { return fMaxGeometryImageStorages; }
    229 
    230     int maxFragmentImageStorages() const { return fMaxFragmentImageStorages; }
    231 
    232     int maxCombinedImageStorages() const { return fMaxCombinedImageStorages; }
    233 
    234     /**
    235      * Given a texture's config, this determines what swizzle must be appended to accesses to the
    236      * texture in generated shader code. Swizzling may be implemented in texture parameters or a
    237      * sampler rather than in the shader. In this case the returned swizzle will always be "rgba".
    238      */
    239     const GrSwizzle& configTextureSwizzle(GrPixelConfig config) const {
    240         return fConfigTextureSwizzle[config];
    241     }
    242 
    243     /** Swizzle that should occur on the fragment shader outputs for a given config. */
    244     const GrSwizzle& configOutputSwizzle(GrPixelConfig config) const {
    245         return fConfigOutputSwizzle[config];
    246     }
    247 
    248     /** Precision qualifier that should be used with a sampler, given its config and visibility. */
    249     GrSLPrecision samplerPrecision(GrPixelConfig config, GrShaderFlags visibility) const {
    250         return static_cast<GrSLPrecision>(fSamplerPrecisions[visibility][config]);
    251     }
    252 
    253     GrGLSLGeneration generation() const { return fGLSLGeneration; }
    254 
    255 private:
    256     /** GrCaps subclasses must call this after filling in the shader precision table. */
    257     void initSamplerPrecisionTable();
    258 
    259     void applyOptionsOverrides(const GrContextOptions& options);
    260 
    261     GrGLSLGeneration fGLSLGeneration;
    262 
    263     bool fShaderDerivativeSupport   : 1;
    264     bool fGeometryShaderSupport     : 1;
    265     bool fPathRenderingSupport      : 1;
    266     bool fDstReadInShaderSupport    : 1;
    267     bool fDualSourceBlendingSupport : 1;
    268     bool fIntegerSupport            : 1;
    269     bool fTexelBufferSupport        : 1;
    270     bool fImageLoadStoreSupport     : 1;
    271     bool fShaderPrecisionVaries     : 1;
    272     bool fDropsTileOnZeroDivide : 1;
    273     bool fFBFetchSupport : 1;
    274     bool fFBFetchNeedsCustomOutput : 1;
    275     bool fBindlessTextureSupport : 1;
    276     bool fUsesPrecisionModifiers : 1;
    277     bool fCanUseAnyFunctionInShader : 1;
    278     bool fFlatInterpolationSupport : 1;
    279     bool fNoPerspectiveInterpolationSupport : 1;
    280     bool fMultisampleInterpolationSupport : 1;
    281     bool fSampleVariablesSupport : 1;
    282     bool fSampleMaskOverrideCoverageSupport : 1;
    283     bool fExternalTextureSupport : 1;
    284     bool fTexelFetchSupport : 1;
    285 
    286     // Used for specific driver bug work arounds
    287     bool fCanUseMinAndAbsTogether : 1;
    288     bool fMustForceNegatedAtanParamToFloat : 1;
    289     bool fAtan2ImplementedAsAtanYOverX : 1;
    290     bool fRequiresLocalOutputColorForFBFetch : 1;
    291     bool fMustImplementGSInvocationsWithLoop : 1;
    292 
    293     PrecisionInfo fFloatPrecisions[kGrShaderTypeCount][kGrSLPrecisionCount];
    294 
    295     const char* fVersionDeclString;
    296 
    297     const char* fShaderDerivativeExtensionString;
    298     const char* fFragCoordConventionsExtensionString;
    299     const char* fSecondaryOutputExtensionString;
    300     const char* fExternalTextureExtensionString;
    301     const char* fTexelBufferExtensionString;
    302     const char* fNoPerspectiveInterpolationExtensionString;
    303     const char* fMultisampleInterpolationExtensionString;
    304     const char* fSampleVariablesExtensionString;
    305     const char* fImageLoadStoreExtensionString;
    306 
    307     const char* fFBFetchColorName;
    308     const char* fFBFetchExtensionString;
    309 
    310     int fMaxVertexSamplers;
    311     int fMaxGeometrySamplers;
    312     int fMaxFragmentSamplers;
    313     int fMaxCombinedSamplers;
    314 
    315     int fMaxVertexImageStorages;
    316     int fMaxGeometryImageStorages;
    317     int fMaxFragmentImageStorages;
    318     int fMaxCombinedImageStorages;
    319 
    320     AdvBlendEqInteraction fAdvBlendEqInteraction;
    321 
    322     GrSwizzle fConfigTextureSwizzle[kGrPixelConfigCnt];
    323     GrSwizzle fConfigOutputSwizzle[kGrPixelConfigCnt];
    324 
    325     uint8_t fSamplerPrecisions[(1 << kGrShaderTypeCount)][kGrPixelConfigCnt];
    326 
    327     friend class GrGLCaps;  // For initialization.
    328     friend class GrVkCaps;
    329     friend class SkSL::ShaderCapsFactory;
    330 };
    331 
    332 #endif
    333