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 "include/core/SkRefCnt.h"
12#include "include/private/GrTypesPriv.h"
13#include "src/gpu/GrSwizzle.h"
14#include "src/gpu/glsl/GrGLSL.h"
15
16namespace SkSL {
17class ShaderCapsFactory;
18}
19
20struct GrContextOptions;
21class SkJSONWriter;
22
23class GrShaderCaps : public SkRefCnt {
24public:
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
52 /**
53 * Some helper functions for encapsulating various extensions to read FB Buffer on openglES
54 *
55 * TODO(joshualitt) On desktop opengl 4.2+ we can achieve something similar to this effect
56 */
57 bool fbFetchSupport() const { return fFBFetchSupport; }
58
59 bool fbFetchNeedsCustomOutput() const { return fFBFetchNeedsCustomOutput; }
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 flatInterpolationSupport() const { return fFlatInterpolationSupport; }
68
69 bool preferFlatInterpolation() const { return fPreferFlatInterpolation; }
70
71 bool noperspectiveInterpolationSupport() const { return fNoPerspectiveInterpolationSupport; }
72
73 bool sampleMaskSupport() const { return fSampleMaskSupport; }
74
75 bool tessellationSupport() const { return fTessellationSupport; }
76
77 bool externalTextureSupport() const { return fExternalTextureSupport; }
78
79 bool vertexIDSupport() const { return fVertexIDSupport; }
80
81 // frexp, ldexp, etc.
82 bool fpManipulationSupport() const { return fFPManipulationSupport; }
83
84 bool floatIs32Bits() const { return fFloatIs32Bits; }
85
86 bool halfIs32Bits() const { return fHalfIs32Bits; }
87
88 bool hasLowFragmentPrecision() const { return fHasLowFragmentPrecision; }
89
90 // SkSL only.
91 bool builtinFMASupport() const { return fBuiltinFMASupport; }
92
93 AdvBlendEqInteraction advBlendEqInteraction() const { return fAdvBlendEqInteraction; }
94
95 bool mustEnableAdvBlendEqs() const {
96 return fAdvBlendEqInteraction >= kGeneralEnable_AdvBlendEqInteraction;
97 }
98
99 bool mustEnableSpecificAdvBlendEqs() const {
100 return fAdvBlendEqInteraction == kSpecificEnables_AdvBlendEqInteraction;
101 }
102
103 bool mustDeclareFragmentShaderOutput() const { return fGLSLGeneration > k110_GrGLSLGeneration; }
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, short ints can't represent every integer in the 16-bit two's complement range as
128 // required by the spec. SKSL will always emit full ints.
129 bool incompleteShortIntPrecision() const { return fIncompleteShortIntPrecision; }
130
131 bool colorSpaceMathNeedsFloat() const { return fColorSpaceMathNeedsFloat; }
132
133 // If true, then conditions in for loops need "&& true" to work around driver bugs.
134 bool addAndTrueToLoopCondition() const { return fAddAndTrueToLoopCondition; }
135
136 // If true, then expressions such as "x && y" or "x || y" are rewritten as
137 // ternary to work around driver bugs.
138 bool unfoldShortCircuitAsTernary() const { return fUnfoldShortCircuitAsTernary; }
139
140 bool emulateAbsIntFunction() const { return fEmulateAbsIntFunction; }
141
142 bool rewriteDoWhileLoops() const { return fRewriteDoWhileLoops; }
143
144 bool removePowWithConstantExponent() const { return fRemovePowWithConstantExponent; }
145
146 bool requiresLocalOutputColorForFBFetch() const { return fRequiresLocalOutputColorForFBFetch; }
147
148 bool mustObfuscateUniformColor() const { return fMustObfuscateUniformColor; }
149
150 // The D3D shader compiler, when targeting PS 3.0 (ie within ANGLE) fails to compile certain
151 // constructs. See detailed comments in GrGLCaps.cpp.
152 bool mustGuardDivisionEvenAfterExplicitZeroCheck() const {
153 return fMustGuardDivisionEvenAfterExplicitZeroCheck;
154 }
155
156 // On Pixel 3, 3a, and 4 devices we've noticed that the simple function:
157 // half4 blend(half4 a, half4 b) { return a.a * b; }
158 // may return (0, 0, 0, 1) when b is (0, 0, 0, 0).
159 bool inBlendModesFailRandomlyForAllZeroVec() const {
160 return fInBlendModesFailRandomlyForAllZeroVec;
161 }
162
163 // On Nexus 6, the GL context can get lost if a shader does not write a value to gl_FragColor.
164 // https://bugs.chromium.org/p/chromium/issues/detail?id=445377
165 bool mustWriteToFragColor() const { return fMustWriteToFragColor; }
166
167 // The Android emulator claims samplerExternalOES is an unknown type if a default precision
168 // statement is made for the type.
169 bool noDefaultPrecisionForExternalSamplers() const {
170 return fNoDefaultPrecisionForExternalSamplers;
171 }
172
173 // The sample mask round rect op draws nothing on several Adreno and Radeon bots. Other ops that
174 // use sample mask while rendering to stencil seem to work fine.
175 // http://skbug.com/8921
176 bool canOnlyUseSampleMaskWithStencil() const { return fCanOnlyUseSampleMaskWithStencil; }
177
178 // Returns the string of an extension that must be enabled in the shader to support
179 // derivatives. If nullptr is returned then no extension needs to be enabled. Before calling
180 // this function, the caller should check that shaderDerivativeSupport exists.
181 const char* shaderDerivativeExtensionString() const {
182 SkASSERT(this->shaderDerivativeSupport());
183 return fShaderDerivativeExtensionString;
184 }
185
186 // Returns the string of an extension that must be enabled in the shader to support geometry
187 // shaders. If nullptr is returned then no extension needs to be enabled. Before calling this
188 // function, the caller must verify that geometryShaderSupport exists.
189 const char* geometryShaderExtensionString() const {
190 SkASSERT(this->geometryShaderSupport());
191 return fGeometryShaderExtensionString;
192 }
193
194 // Returns the string of an extension that must be enabled in the shader to support
195 // geometry shader invocations. If nullptr is returned then no extension needs to be enabled.
196 // Before calling this function, the caller must verify that gsInvocationsSupport exists.
197 const char* gsInvocationsExtensionString() const {
198 SkASSERT(this->gsInvocationsSupport());
199 return fGSInvocationsExtensionString;
200 }
201
202 // Returns the string of an extension that will do all necessary coord transfomations needed
203 // when reading the fragment position. If such an extension does not exisits, this function
204 // returns a nullptr, and all transforms of the frag position must be done manually in the
205 // shader.
206 const char* fragCoordConventionsExtensionString() const {
207 return fFragCoordConventionsExtensionString;
208 }
209
210 // This returns the name of an extension that must be enabled in the shader, if such a thing is
211 // required in order to use a secondary output in the shader. This returns a nullptr if no such
212 // extension is required. However, the return value of this function does not say whether dual
213 // source blending is supported.
214 const char* secondaryOutputExtensionString() const { return fSecondaryOutputExtensionString; }
215
216 // This returns the name of an extension that must be enabled in the shader to support external
217 // textures. In some cases, two extensions must be enabled - the second extension is returned
218 // by secondExternalTextureExtensionString(). If that function returns nullptr, then only one
219 // extension is required.
220 const char* externalTextureExtensionString() const {
221 SkASSERT(this->externalTextureSupport());
222 return fExternalTextureExtensionString;
223 }
224
225 const char* secondExternalTextureExtensionString() const {
226 SkASSERT(this->externalTextureSupport());
227 return fSecondExternalTextureExtensionString;
228 }
229
230 const char* noperspectiveInterpolationExtensionString() const {
231 SkASSERT(this->noperspectiveInterpolationSupport());
232 return fNoPerspectiveInterpolationExtensionString;
233 }
234
235 const char* sampleVariablesExtensionString() const {
236 SkASSERT(this->sampleMaskSupport());
237 return fSampleVariablesExtensionString;
238 }
239
240 const char* tessellationExtensionString() const {
241 SkASSERT(this->tessellationSupport());
242 return fTessellationExtensionString;
243 }
244
245 int maxFragmentSamplers() const { return fMaxFragmentSamplers; }
246
247 bool textureSwizzleAppliedInShader() const { return fTextureSwizzleAppliedInShader; }
248
249 GrGLSLGeneration generation() const { return fGLSLGeneration; }
250
251private:
252 void applyOptionsOverrides(const GrContextOptions& options);
253
254 GrGLSLGeneration fGLSLGeneration;
255
256 bool fShaderDerivativeSupport : 1;
257 bool fGeometryShaderSupport : 1;
258 bool fGSInvocationsSupport : 1;
259 bool fPathRenderingSupport : 1;
260 bool fDstReadInShaderSupport : 1;
261 bool fDualSourceBlendingSupport : 1;
262 bool fIntegerSupport : 1;
263 bool fFBFetchSupport : 1;
264 bool fFBFetchNeedsCustomOutput : 1;
265 bool fUsesPrecisionModifiers : 1;
266 bool fFlatInterpolationSupport : 1;
267 bool fPreferFlatInterpolation : 1;
268 bool fNoPerspectiveInterpolationSupport : 1;
269 bool fSampleMaskSupport : 1;
270 bool fTessellationSupport : 1;
271 bool fExternalTextureSupport : 1;
272 bool fVertexIDSupport : 1;
273 bool fFPManipulationSupport : 1;
274 bool fFloatIs32Bits : 1;
275 bool fHalfIs32Bits : 1;
276 bool fHasLowFragmentPrecision : 1;
277 bool fTextureSwizzleAppliedInShader : 1;
278
279 // Used by SkSL to know when to generate polyfills.
280 bool fBuiltinFMASupport : 1;
281
282 // Used for specific driver bug work arounds
283 bool fCanUseAnyFunctionInShader : 1;
284 bool fCanUseMinAndAbsTogether : 1;
285 bool fCanUseFractForNegativeValues : 1;
286 bool fMustForceNegatedAtanParamToFloat : 1;
287 bool fAtan2ImplementedAsAtanYOverX : 1;
288 bool fMustDoOpBetweenFloorAndAbs : 1;
289 bool fRequiresLocalOutputColorForFBFetch : 1;
290 bool fMustObfuscateUniformColor : 1;
291 bool fMustGuardDivisionEvenAfterExplicitZeroCheck : 1;
292 bool fInBlendModesFailRandomlyForAllZeroVec : 1;
293 bool fCanUseFragCoord : 1;
294 bool fIncompleteShortIntPrecision : 1;
295 bool fAddAndTrueToLoopCondition : 1;
296 bool fUnfoldShortCircuitAsTernary : 1;
297 bool fEmulateAbsIntFunction : 1;
298 bool fRewriteDoWhileLoops : 1;
299 bool fRemovePowWithConstantExponent : 1;
300 bool fMustWriteToFragColor : 1;
301 bool fNoDefaultPrecisionForExternalSamplers : 1;
302 bool fCanOnlyUseSampleMaskWithStencil : 1;
303 bool fColorSpaceMathNeedsFloat : 1;
304
305 const char* fVersionDeclString;
306
307 const char* fShaderDerivativeExtensionString;
308 const char* fGeometryShaderExtensionString;
309 const char* fGSInvocationsExtensionString;
310 const char* fFragCoordConventionsExtensionString;
311 const char* fSecondaryOutputExtensionString;
312 const char* fExternalTextureExtensionString;
313 const char* fSecondExternalTextureExtensionString;
314 const char* fNoPerspectiveInterpolationExtensionString;
315 const char* fSampleVariablesExtensionString;
316 const char* fTessellationExtensionString;
317
318 const char* fFBFetchColorName;
319 const char* fFBFetchExtensionString;
320
321 int fMaxFragmentSamplers;
322
323 AdvBlendEqInteraction fAdvBlendEqInteraction;
324
325 friend class GrCaps; // For initialization.
326 friend class GrDawnCaps;
327 friend class GrD3DCaps;
328 friend class GrGLCaps;
329 friend class GrMockCaps;
330 friend class GrMtlCaps;
331 friend class GrVkCaps;
332 friend class SkSL::ShaderCapsFactory;
333};
334
335#endif
336