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 class SkJSONWriter;
     20 
     21 class GrShaderCaps : public SkRefCnt {
     22 public:
     23     /**
     24     * Indicates how GLSL must interact with advanced blend equations. The KHR extension requires
     25     * special layout qualifiers in the fragment shader.
     26     */
     27     enum AdvBlendEqInteraction {
     28         kNotSupported_AdvBlendEqInteraction,     //<! No _blend_equation_advanced extension
     29         kAutomatic_AdvBlendEqInteraction,        //<! No interaction required
     30         kGeneralEnable_AdvBlendEqInteraction,    //<! layout(blend_support_all_equations) out
     31         kSpecificEnables_AdvBlendEqInteraction,  //<! Specific layout qualifiers per equation
     32 
     33         kLast_AdvBlendEqInteraction = kSpecificEnables_AdvBlendEqInteraction
     34     };
     35 
     36     GrShaderCaps(const GrContextOptions&);
     37 
     38     void dumpJSON(SkJSONWriter*) const;
     39 
     40     bool shaderDerivativeSupport() const { return fShaderDerivativeSupport; }
     41     bool geometryShaderSupport() const { return fGeometryShaderSupport; }
     42     bool gsInvocationsSupport() const { return fGSInvocationsSupport; }
     43     bool pathRenderingSupport() const { return fPathRenderingSupport; }
     44     bool dstReadInShaderSupport() const { return fDstReadInShaderSupport; }
     45     bool dualSourceBlendingSupport() const { return fDualSourceBlendingSupport; }
     46     bool integerSupport() const { return fIntegerSupport; }
     47     bool texelBufferSupport() const { return fTexelBufferSupport; }
     48     int imageLoadStoreSupport() const { return fImageLoadStoreSupport; }
     49 
     50     /**
     51      * Some helper functions for encapsulating various extensions to read FB Buffer on openglES
     52      *
     53      * TODO(joshualitt) On desktop opengl 4.2+ we can achieve something similar to this effect
     54      */
     55     bool fbFetchSupport() const { return fFBFetchSupport; }
     56 
     57     bool fbFetchNeedsCustomOutput() const { return fFBFetchNeedsCustomOutput; }
     58 
     59     bool bindlessTextureSupport() const { return fBindlessTextureSupport; }
     60 
     61     const char* versionDeclString() const { return fVersionDeclString; }
     62 
     63     const char* fbFetchColorName() const { return fFBFetchColorName; }
     64 
     65     const char* fbFetchExtensionString() const { return fFBFetchExtensionString; }
     66 
     67     bool dropsTileOnZeroDivide() const { return fDropsTileOnZeroDivide; }
     68 
     69     bool flatInterpolationSupport() const { return fFlatInterpolationSupport; }
     70 
     71     bool preferFlatInterpolation() const { return fPreferFlatInterpolation; }
     72 
     73     bool noperspectiveInterpolationSupport() const { return fNoPerspectiveInterpolationSupport; }
     74 
     75     bool multisampleInterpolationSupport() const { return fMultisampleInterpolationSupport; }
     76 
     77     bool sampleVariablesSupport() const { return fSampleVariablesSupport; }
     78 
     79     bool sampleMaskOverrideCoverageSupport() const { return fSampleMaskOverrideCoverageSupport; }
     80 
     81     bool externalTextureSupport() const { return fExternalTextureSupport; }
     82 
     83     bool texelFetchSupport() const { return fTexelFetchSupport; }
     84 
     85     bool vertexIDSupport() const { return fVertexIDSupport; }
     86 
     87     bool floatIs32Bits() const { return fFloatIs32Bits; }
     88 
     89     bool halfIs32Bits() const { return fHalfIs32Bits; }
     90 
     91     AdvBlendEqInteraction advBlendEqInteraction() const { return fAdvBlendEqInteraction; }
     92 
     93     bool mustEnableAdvBlendEqs() const {
     94         return fAdvBlendEqInteraction >= kGeneralEnable_AdvBlendEqInteraction;
     95     }
     96 
     97     bool mustEnableSpecificAdvBlendEqs() const {
     98         return fAdvBlendEqInteraction == kSpecificEnables_AdvBlendEqInteraction;
     99     }
    100 
    101     bool mustDeclareFragmentShaderOutput() const {
    102         return fGLSLGeneration > k110_GrGLSLGeneration;
    103     }
    104 
    105     bool usesPrecisionModifiers() const { return fUsesPrecisionModifiers; }
    106 
    107     // Returns whether we can use the glsl function any() in our shader code.
    108     bool canUseAnyFunctionInShader() const { return fCanUseAnyFunctionInShader; }
    109 
    110     bool canUseMinAndAbsTogether() const { return fCanUseMinAndAbsTogether; }
    111 
    112     bool canUseFractForNegativeValues() const { return fCanUseFractForNegativeValues; }
    113 
    114     bool mustForceNegatedAtanParamToFloat() const { return fMustForceNegatedAtanParamToFloat; }
    115 
    116     // Returns whether a device incorrectly implements atan(y,x) as atan(y/x)
    117     bool atan2ImplementedAsAtanYOverX() const { return fAtan2ImplementedAsAtanYOverX; }
    118 
    119     // If this returns true some operation (could be a no op) must be called between floor and abs
    120     // to make sure the driver compiler doesn't inline them together which can cause a driver bug in
    121     // the shader.
    122     bool mustDoOpBetweenFloorAndAbs() const { return fMustDoOpBetweenFloorAndAbs; }
    123 
    124     // If false, SkSL uses a workaround so that sk_FragCoord doesn't actually query gl_FragCoord
    125     bool canUseFragCoord() const { return fCanUseFragCoord; }
    126 
    127     // If true interpolated vertex shader outputs are inaccurate.
    128     bool interpolantsAreInaccurate() const { return fInterpolantsAreInaccurate; }
    129 
    130     bool requiresLocalOutputColorForFBFetch() const { return fRequiresLocalOutputColorForFBFetch; }
    131 
    132     bool mustObfuscateUniformColor() const { return fMustObfuscateUniformColor; }
    133 
    134     // The D3D shader compiler, when targeting PS 3.0 (ie within ANGLE) fails to compile certain
    135     // constructs. See detailed comments in GrGLCaps.cpp.
    136     bool mustGuardDivisionEvenAfterExplicitZeroCheck() const {
    137         return fMustGuardDivisionEvenAfterExplicitZeroCheck;
    138     }
    139 
    140     // Returns the string of an extension that must be enabled in the shader to support
    141     // derivatives. If nullptr is returned then no extension needs to be enabled. Before calling
    142     // this function, the caller should check that shaderDerivativeSupport exists.
    143     const char* shaderDerivativeExtensionString() const {
    144         SkASSERT(this->shaderDerivativeSupport());
    145         return fShaderDerivativeExtensionString;
    146     }
    147 
    148     // Returns the string of an extension that must be enabled in the shader to support geometry
    149     // shaders. If nullptr is returned then no extension needs to be enabled. Before calling this
    150     // function, the caller must verify that geometryShaderSupport exists.
    151     const char* geometryShaderExtensionString() const {
    152         SkASSERT(this->geometryShaderSupport());
    153         return fGeometryShaderExtensionString;
    154     }
    155 
    156     // Returns the string of an extension that must be enabled in the shader to support
    157     // geometry shader invocations. If nullptr is returned then no extension needs to be enabled.
    158     // Before calling this function, the caller must verify that gsInvocationsSupport exists.
    159     const char* gsInvocationsExtensionString() const {
    160         SkASSERT(this->gsInvocationsSupport());
    161         return fGSInvocationsExtensionString;
    162     }
    163 
    164     // Returns the string of an extension that will do all necessary coord transfomations needed
    165     // when reading the fragment position. If such an extension does not exisits, this function
    166     // returns a nullptr, and all transforms of the frag position must be done manually in the
    167     // shader.
    168     const char* fragCoordConventionsExtensionString() const {
    169         return fFragCoordConventionsExtensionString;
    170     }
    171 
    172     // This returns the name of an extension that must be enabled in the shader, if such a thing is
    173     // required in order to use a secondary output in the shader. This returns a nullptr if no such
    174     // extension is required. However, the return value of this function does not say whether dual
    175     // source blending is supported.
    176     const char* secondaryOutputExtensionString() const {
    177         return fSecondaryOutputExtensionString;
    178     }
    179 
    180     const char* externalTextureExtensionString() const {
    181         SkASSERT(this->externalTextureSupport());
    182         return fExternalTextureExtensionString;
    183     }
    184 
    185     const char* texelBufferExtensionString() const {
    186         SkASSERT(this->texelBufferSupport());
    187         return fTexelBufferExtensionString;
    188     }
    189 
    190     const char* noperspectiveInterpolationExtensionString() const {
    191         SkASSERT(this->noperspectiveInterpolationSupport());
    192         return fNoPerspectiveInterpolationExtensionString;
    193     }
    194 
    195     const char* multisampleInterpolationExtensionString() const {
    196         SkASSERT(this->multisampleInterpolationSupport());
    197         return fMultisampleInterpolationExtensionString;
    198     }
    199 
    200     const char* sampleVariablesExtensionString() const {
    201         SkASSERT(this->sampleVariablesSupport());
    202         return fSampleVariablesExtensionString;
    203     }
    204 
    205     const char* imageLoadStoreExtensionString() const {
    206         SkASSERT(this->imageLoadStoreSupport());
    207         return fImageLoadStoreExtensionString;
    208     }
    209 
    210     int maxVertexSamplers() const { return fMaxVertexSamplers; }
    211 
    212     int maxGeometrySamplers() const { return fMaxGeometrySamplers; }
    213 
    214     int maxFragmentSamplers() const { return fMaxFragmentSamplers; }
    215 
    216     int maxCombinedSamplers() const { return fMaxCombinedSamplers; }
    217 
    218     /**
    219      * In general using multiple texture units for image rendering seems to be a win at smaller
    220      * sizes of dst rects and a loss at larger sizes. Dst rects above this pixel area threshold will
    221      * not use multitexturing.
    222      */
    223     size_t disableImageMultitexturingDstRectAreaThreshold() const {
    224         return fDisableImageMultitexturingDstRectAreaThreshold;
    225     }
    226 
    227     /**
    228      * Given a texture's config, this determines what swizzle must be appended to accesses to the
    229      * texture in generated shader code. Swizzling may be implemented in texture parameters or a
    230      * sampler rather than in the shader. In this case the returned swizzle will always be "rgba".
    231      */
    232     const GrSwizzle& configTextureSwizzle(GrPixelConfig config) const {
    233         return fConfigTextureSwizzle[config];
    234     }
    235 
    236     /** Swizzle that should occur on the fragment shader outputs for a given config. */
    237     const GrSwizzle& configOutputSwizzle(GrPixelConfig config) const {
    238         return fConfigOutputSwizzle[config];
    239     }
    240 
    241     GrGLSLGeneration generation() const { return fGLSLGeneration; }
    242 
    243 private:
    244     void applyOptionsOverrides(const GrContextOptions& options);
    245 
    246     GrGLSLGeneration fGLSLGeneration;
    247 
    248     bool fShaderDerivativeSupport   : 1;
    249     bool fGeometryShaderSupport     : 1;
    250     bool fGSInvocationsSupport      : 1;
    251     bool fPathRenderingSupport      : 1;
    252     bool fDstReadInShaderSupport    : 1;
    253     bool fDualSourceBlendingSupport : 1;
    254     bool fIntegerSupport            : 1;
    255     bool fTexelBufferSupport        : 1;
    256     bool fImageLoadStoreSupport     : 1;
    257     bool fDropsTileOnZeroDivide : 1;
    258     bool fFBFetchSupport : 1;
    259     bool fFBFetchNeedsCustomOutput : 1;
    260     bool fBindlessTextureSupport : 1;
    261     bool fUsesPrecisionModifiers : 1;
    262     bool fFlatInterpolationSupport : 1;
    263     bool fPreferFlatInterpolation : 1;
    264     bool fNoPerspectiveInterpolationSupport : 1;
    265     bool fMultisampleInterpolationSupport : 1;
    266     bool fSampleVariablesSupport : 1;
    267     bool fSampleMaskOverrideCoverageSupport : 1;
    268     bool fExternalTextureSupport : 1;
    269     bool fTexelFetchSupport : 1;
    270     bool fVertexIDSupport : 1;
    271     bool fFloatIs32Bits : 1;
    272     bool fHalfIs32Bits : 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 fInterpolantsAreInaccurate : 1;
    286 
    287     const char* fVersionDeclString;
    288 
    289     const char* fShaderDerivativeExtensionString;
    290     const char* fGeometryShaderExtensionString;
    291     const char* fGSInvocationsExtensionString;
    292     const char* fFragCoordConventionsExtensionString;
    293     const char* fSecondaryOutputExtensionString;
    294     const char* fExternalTextureExtensionString;
    295     const char* fTexelBufferExtensionString;
    296     const char* fNoPerspectiveInterpolationExtensionString;
    297     const char* fMultisampleInterpolationExtensionString;
    298     const char* fSampleVariablesExtensionString;
    299     const char* fImageLoadStoreExtensionString;
    300 
    301     const char* fFBFetchColorName;
    302     const char* fFBFetchExtensionString;
    303 
    304     int fMaxVertexSamplers;
    305     int fMaxGeometrySamplers;
    306     int fMaxFragmentSamplers;
    307     int fMaxCombinedSamplers;
    308 
    309     size_t fDisableImageMultitexturingDstRectAreaThreshold;
    310 
    311     AdvBlendEqInteraction fAdvBlendEqInteraction;
    312 
    313     GrSwizzle fConfigTextureSwizzle[kGrPixelConfigCnt];
    314     GrSwizzle fConfigOutputSwizzle[kGrPixelConfigCnt];
    315 
    316     friend class GrCaps;  // For initialization.
    317     friend class GrGLCaps;
    318     friend class GrMockCaps;
    319     friend class GrMtlCaps;
    320     friend class GrVkCaps;
    321     friend class SkSL::ShaderCapsFactory;
    322 };
    323 
    324 #endif
    325