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} // namespace SkSL
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 externalTextureSupport() const { return fExternalTextureSupport; }
76
77 bool vertexIDSupport() const { return fVertexIDSupport; }
78
79 // frexp, ldexp, etc.
80 bool fpManipulationSupport() const { return fFPManipulationSupport; }
81
82 bool floatIs32Bits() const { return fFloatIs32Bits; }
83
84 bool halfIs32Bits() const { return fHalfIs32Bits; }
85
86 bool hasLowFragmentPrecision() const { return fHasLowFragmentPrecision; }
87
88 // SkSL only.
89 bool builtinFMASupport() const { return fBuiltinFMASupport; }
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 { return fGLSLGeneration > k110_GrGLSLGeneration; }
102
103 bool usesPrecisionModifiers() const { return fUsesPrecisionModifiers; }
104
105 // Returns whether we can use the glsl function any() in our shader code.
106 bool canUseAnyFunctionInShader() const { return fCanUseAnyFunctionInShader; }
107
108 bool canUseMinAndAbsTogether() const { return fCanUseMinAndAbsTogether; }
109
110 bool canUseFractForNegativeValues() const { return fCanUseFractForNegativeValues; }
111
112 bool mustForceNegatedAtanParamToFloat() const { return fMustForceNegatedAtanParamToFloat; }
113
114 // Returns whether a device incorrectly implements atan(y,x) as atan(y/x)
115 bool atan2ImplementedAsAtanYOverX() const { return fAtan2ImplementedAsAtanYOverX; }
116
117 // If this returns true some operation (could be a no op) must be called between floor and abs
118 // to make sure the driver compiler doesn't inline them together which can cause a driver bug in
119 // the shader.
120 bool mustDoOpBetweenFloorAndAbs() const { return fMustDoOpBetweenFloorAndAbs; }
121
122 // If false, SkSL uses a workaround so that sk_FragCoord doesn't actually query gl_FragCoord
123 bool canUseFragCoord() const { return fCanUseFragCoord; }
124
125 // If true, short ints can't represent every integer in the 16-bit two's complement range as
126 // required by the spec. SKSL will always emit full ints.
127 bool incompleteShortIntPrecision() const { return fIncompleteShortIntPrecision; }
128
129 bool colorSpaceMathNeedsFloat() const { return fColorSpaceMathNeedsFloat; }
130
131 // If true, then conditions in for loops need "&& true" to work around driver bugs.
132 bool addAndTrueToLoopCondition() const { return fAddAndTrueToLoopCondition; }
133
134 // If true, then expressions such as "x && y" or "x || y" are rewritten as
135 // ternary to work around driver bugs.
136 bool unfoldShortCircuitAsTernary() const { return fUnfoldShortCircuitAsTernary; }
137
138 bool emulateAbsIntFunction() const { return fEmulateAbsIntFunction; }
139
140 bool rewriteDoWhileLoops() const { return fRewriteDoWhileLoops; }
141
142 bool removePowWithConstantExponent() const { return fRemovePowWithConstantExponent; }
143
144 bool requiresLocalOutputColorForFBFetch() const { return fRequiresLocalOutputColorForFBFetch; }
145
146 bool mustObfuscateUniformColor() const { return fMustObfuscateUniformColor; }
147
148 // The D3D shader compiler, when targeting PS 3.0 (ie within ANGLE) fails to compile certain
149 // constructs. See detailed comments in GrGLCaps.cpp.
150 bool mustGuardDivisionEvenAfterExplicitZeroCheck() const {
151 return fMustGuardDivisionEvenAfterExplicitZeroCheck;
152 }
153
154 // On Pixel 3, 3a, and 4 devices we've noticed that the simple function:
155 // half4 blend(half4 a, half4 b) { return a.a * b; }
156 // may return (0, 0, 0, 1) when b is (0, 0, 0, 0).
157 bool inBlendModesFailRandomlyForAllZeroVec() const {
158 return fInBlendModesFailRandomlyForAllZeroVec;
159 }
160
161 // On Nexus 6, the GL context can get lost if a shader does not write a value to gl_FragColor.
162 // https://bugs.chromium.org/p/chromium/issues/detail?id=445377
163 bool mustWriteToFragColor() const { return fMustWriteToFragColor; }
164
165 // The Android emulator claims samplerExternalOES is an unknown type if a default precision
166 // statement is made for the type.
167 bool noDefaultPrecisionForExternalSamplers() const {
168 return fNoDefaultPrecisionForExternalSamplers;
169 }
170
171 // The sample mask round rect op draws nothing on several Adreno and Radeon bots. Other ops that
172 // use sample mask while rendering to stencil seem to work fine.
173 // http://skbug.com/8921
174 bool canOnlyUseSampleMaskWithStencil() const { return fCanOnlyUseSampleMaskWithStencil; }
175
176 // ANGLE disallows do loops altogether, and we're seeing crashes on Tegra3 with do loops in at
177 // least some cases.
178 bool canUseDoLoops() const { return fCanUseDoLoops; }
179
180 // Returns the string of an extension that must be enabled in the shader to support
181 // derivatives. If nullptr is returned then no extension needs to be enabled. Before calling
182 // this function, the caller should check that shaderDerivativeSupport exists.
183 const char* shaderDerivativeExtensionString() const {
184 SkASSERT(this->shaderDerivativeSupport());
185 return fShaderDerivativeExtensionString;
186 }
187
188 // Returns the string of an extension that must be enabled in the shader to support geometry
189 // shaders. If nullptr is returned then no extension needs to be enabled. Before calling this
190 // function, the caller must verify that geometryShaderSupport exists.
191 const char* geometryShaderExtensionString() const {
192 SkASSERT(this->geometryShaderSupport());
193 return fGeometryShaderExtensionString;
194 }
195
196 // Returns the string of an extension that must be enabled in the shader to support
197 // geometry shader invocations. If nullptr is returned then no extension needs to be enabled.
198 // Before calling this function, the caller must verify that gsInvocationsSupport exists.
199 const char* gsInvocationsExtensionString() const {
200 SkASSERT(this->gsInvocationsSupport());
201 return fGSInvocationsExtensionString;
202 }
203
204 // Returns the string of an extension that will do all necessary coord transfomations needed
205 // when reading the fragment position. If such an extension does not exisits, this function
206 // returns a nullptr, and all transforms of the frag position must be done manually in the
207 // shader.
208 const char* fragCoordConventionsExtensionString() const {
209 return fFragCoordConventionsExtensionString;
210 }
211
212 // This returns the name of an extension that must be enabled in the shader, if such a thing is
213 // required in order to use a secondary output in the shader. This returns a nullptr if no such
214 // extension is required. However, the return value of this function does not say whether dual
215 // source blending is supported.
216 const char* secondaryOutputExtensionString() const { return fSecondaryOutputExtensionString; }
217
218 // This returns the name of an extension that must be enabled in the shader to support external
219 // textures. In some cases, two extensions must be enabled - the second extension is returned
220 // by secondExternalTextureExtensionString(). If that function returns nullptr, then only one
221 // extension is required.
222 const char* externalTextureExtensionString() const {
223 SkASSERT(this->externalTextureSupport());
224 return fExternalTextureExtensionString;
225 }
226
227 const char* secondExternalTextureExtensionString() const {
228 SkASSERT(this->externalTextureSupport());
229 return fSecondExternalTextureExtensionString;
230 }
231
232 const char* noperspectiveInterpolationExtensionString() const {
233 SkASSERT(this->noperspectiveInterpolationSupport());
234 return fNoPerspectiveInterpolationExtensionString;
235 }
236
237 const char* sampleVariablesExtensionString() const {
238 SkASSERT(this->sampleMaskSupport());
239 return fSampleVariablesExtensionString;
240 }
241
242 const char* tessellationExtensionString() const {
243 SkASSERT(this->tessellationSupport());
244 return fTessellationExtensionString;
245 }
246
247 int maxFragmentSamplers() const { return fMaxFragmentSamplers; }
248
249 // Maximum number of segments a tessellation edge can be divided into.
250 int maxTessellationSegments() const { return fMaxTessellationSegments; }
251
252 bool tessellationSupport() const { return SkToBool(fMaxTessellationSegments);}
253
254 bool textureSwizzleAppliedInShader() const { return fTextureSwizzleAppliedInShader; }
255
256 GrGLSLGeneration generation() const { return fGLSLGeneration; }
257
258private:
259 void applyOptionsOverrides(const GrContextOptions& options);
260
261 GrGLSLGeneration fGLSLGeneration;
262
263 bool fShaderDerivativeSupport : 1;
264 bool fGeometryShaderSupport : 1;
265 bool fGSInvocationsSupport : 1;
266 bool fPathRenderingSupport : 1;
267 bool fDstReadInShaderSupport : 1;
268 bool fDualSourceBlendingSupport : 1;
269 bool fIntegerSupport : 1;
270 bool fFBFetchSupport : 1;
271 bool fFBFetchNeedsCustomOutput : 1;
272 bool fUsesPrecisionModifiers : 1;
273 bool fFlatInterpolationSupport : 1;
274 bool fPreferFlatInterpolation : 1;
275 bool fNoPerspectiveInterpolationSupport : 1;
276 bool fSampleMaskSupport : 1;
277 bool fExternalTextureSupport : 1;
278 bool fVertexIDSupport : 1;
279 bool fFPManipulationSupport : 1;
280 bool fFloatIs32Bits : 1;
281 bool fHalfIs32Bits : 1;
282 bool fHasLowFragmentPrecision : 1;
283 bool fTextureSwizzleAppliedInShader : 1;
284
285 // Used by SkSL to know when to generate polyfills.
286 bool fBuiltinFMASupport : 1;
287
288 // Used for specific driver bug work arounds
289 bool fCanUseAnyFunctionInShader : 1;
290 bool fCanUseMinAndAbsTogether : 1;
291 bool fCanUseFractForNegativeValues : 1;
292 bool fMustForceNegatedAtanParamToFloat : 1;
293 bool fAtan2ImplementedAsAtanYOverX : 1;
294 bool fMustDoOpBetweenFloorAndAbs : 1;
295 bool fRequiresLocalOutputColorForFBFetch : 1;
296 bool fMustObfuscateUniformColor : 1;
297 bool fMustGuardDivisionEvenAfterExplicitZeroCheck : 1;
298 bool fInBlendModesFailRandomlyForAllZeroVec : 1;
299 bool fCanUseFragCoord : 1;
300 bool fIncompleteShortIntPrecision : 1;
301 bool fAddAndTrueToLoopCondition : 1;
302 bool fUnfoldShortCircuitAsTernary : 1;
303 bool fEmulateAbsIntFunction : 1;
304 bool fRewriteDoWhileLoops : 1;
305 bool fRemovePowWithConstantExponent : 1;
306 bool fMustWriteToFragColor : 1;
307 bool fNoDefaultPrecisionForExternalSamplers : 1;
308 bool fCanOnlyUseSampleMaskWithStencil : 1;
309 bool fColorSpaceMathNeedsFloat : 1;
310 bool fCanUseDoLoops : 1;
311
312 const char* fVersionDeclString;
313
314 const char* fShaderDerivativeExtensionString;
315 const char* fGeometryShaderExtensionString;
316 const char* fGSInvocationsExtensionString;
317 const char* fFragCoordConventionsExtensionString;
318 const char* fSecondaryOutputExtensionString;
319 const char* fExternalTextureExtensionString;
320 const char* fSecondExternalTextureExtensionString;
321 const char* fNoPerspectiveInterpolationExtensionString;
322 const char* fSampleVariablesExtensionString;
323 const char* fTessellationExtensionString;
324
325 const char* fFBFetchColorName;
326 const char* fFBFetchExtensionString;
327
328 int fMaxFragmentSamplers;
329 int fMaxTessellationSegments;
330
331 AdvBlendEqInteraction fAdvBlendEqInteraction;
332
333 friend class GrCaps; // For initialization.
334 friend class GrDawnCaps;
335 friend class GrD3DCaps;
336 friend class GrGLCaps;
337 friend class GrMockCaps;
338 friend class GrMtlCaps;
339 friend class GrVkCaps;
340 friend class SkSL::ShaderCapsFactory;
341};
342
343#endif
344