1 | /* |
2 | * Copyright 2016 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 SKSL_UTIL |
9 | #define SKSL_UTIL |
10 | |
11 | #include <cstdarg> |
12 | #include <memory> |
13 | #include "stdlib.h" |
14 | #include "string.h" |
15 | #include "src/sksl/SkSLDefines.h" |
16 | #include "src/sksl/SkSLLexer.h" |
17 | |
18 | #ifndef SKSL_STANDALONE |
19 | #include "include/core/SkTypes.h" |
20 | #include "include/private/GrTypesPriv.h" |
21 | #if SK_SUPPORT_GPU |
22 | #include "include/gpu/GrContextOptions.h" |
23 | #include "src/gpu/GrShaderCaps.h" |
24 | #endif // SK_SUPPORT_GPU |
25 | #endif // SKSL_STANDALONE |
26 | |
27 | class GrShaderCaps; |
28 | |
29 | namespace SkSL { |
30 | |
31 | class Context; |
32 | class OutputStream; |
33 | class StringStream; |
34 | class Type; |
35 | |
36 | #if defined(SKSL_STANDALONE) || !SK_SUPPORT_GPU |
37 | |
38 | // we're being compiled standalone, so we don't have access to caps... |
39 | enum GrGLSLGeneration { |
40 | k110_GrGLSLGeneration, |
41 | k130_GrGLSLGeneration, |
42 | k140_GrGLSLGeneration, |
43 | k150_GrGLSLGeneration, |
44 | k330_GrGLSLGeneration, |
45 | k400_GrGLSLGeneration, |
46 | k420_GrGLSLGeneration, |
47 | k310es_GrGLSLGeneration, |
48 | k320es_GrGLSLGeneration, |
49 | }; |
50 | |
51 | #define SKSL_CAPS_CLASS StandaloneShaderCaps |
52 | class StandaloneShaderCaps { |
53 | public: |
54 | GrGLSLGeneration generation() const { |
55 | return k400_GrGLSLGeneration; |
56 | } |
57 | |
58 | bool atan2ImplementedAsAtanYOverX() const { |
59 | return false; |
60 | } |
61 | |
62 | bool canUseMinAndAbsTogether() const { |
63 | return true; |
64 | } |
65 | |
66 | bool mustForceNegatedAtanParamToFloat() const { |
67 | return false; |
68 | } |
69 | |
70 | bool shaderDerivativeSupport() const { |
71 | return true; |
72 | } |
73 | |
74 | bool usesPrecisionModifiers() const { |
75 | return true; |
76 | } |
77 | |
78 | bool mustDeclareFragmentShaderOutput() const { |
79 | return true; |
80 | } |
81 | |
82 | bool fbFetchSupport() const { |
83 | return true; |
84 | } |
85 | |
86 | bool fbFetchNeedsCustomOutput() const { |
87 | return false; |
88 | } |
89 | |
90 | bool flatInterpolationSupport() const { |
91 | return true; |
92 | } |
93 | |
94 | bool noperspectiveInterpolationSupport() const { |
95 | return true; |
96 | } |
97 | |
98 | bool multisampleInterpolationSupport() const { |
99 | return true; |
100 | } |
101 | |
102 | bool sampleMaskSupport() const { |
103 | return true; |
104 | } |
105 | |
106 | bool externalTextureSupport() const { |
107 | return true; |
108 | } |
109 | |
110 | bool mustDoOpBetweenFloorAndAbs() const { |
111 | return false; |
112 | } |
113 | |
114 | bool mustGuardDivisionEvenAfterExplicitZeroCheck() const { |
115 | return false; |
116 | } |
117 | |
118 | bool inBlendModesFailRandomlyForAllZeroVec() const { |
119 | return false; |
120 | } |
121 | |
122 | bool mustEnableAdvBlendEqs() const { |
123 | return false; |
124 | } |
125 | |
126 | bool mustEnableSpecificAdvBlendEqs() const { |
127 | return false; |
128 | } |
129 | |
130 | bool canUseAnyFunctionInShader() const { |
131 | return false; |
132 | } |
133 | |
134 | bool noDefaultPrecisionForExternalSamplers() const { |
135 | return false; |
136 | } |
137 | |
138 | bool floatIs32Bits() const { |
139 | return true; |
140 | } |
141 | |
142 | bool integerSupport() const { |
143 | return false; |
144 | } |
145 | |
146 | bool builtinFMASupport() const { |
147 | return true; |
148 | } |
149 | |
150 | bool canUseDoLoops() const { |
151 | // we define this to false in standalone so we don't use do loops while inlining in FP files |
152 | // (which would then, being baked in, end up being used even in contexts where do loops are |
153 | // not allowed) |
154 | return false; |
155 | } |
156 | |
157 | const char* shaderDerivativeExtensionString() const { |
158 | return nullptr; |
159 | } |
160 | |
161 | const char* fragCoordConventionsExtensionString() const { |
162 | return nullptr; |
163 | } |
164 | |
165 | const char* geometryShaderExtensionString() const { |
166 | return nullptr; |
167 | } |
168 | |
169 | const char* gsInvocationsExtensionString() const { |
170 | return nullptr; |
171 | } |
172 | |
173 | const char* externalTextureExtensionString() const { |
174 | return nullptr; |
175 | } |
176 | |
177 | const char* secondExternalTextureExtensionString() const { |
178 | return nullptr; |
179 | } |
180 | |
181 | const char* versionDeclString() const { |
182 | return "" ; |
183 | } |
184 | |
185 | bool gsInvocationsSupport() const { |
186 | return true; |
187 | } |
188 | |
189 | bool canUseFractForNegativeValues() const { |
190 | return true; |
191 | } |
192 | |
193 | bool canUseFragCoord() const { |
194 | return true; |
195 | } |
196 | |
197 | bool incompleteShortIntPrecision() const { |
198 | return false; |
199 | } |
200 | |
201 | bool addAndTrueToLoopCondition() const { |
202 | return false; |
203 | } |
204 | |
205 | bool unfoldShortCircuitAsTernary() const { |
206 | return false; |
207 | } |
208 | |
209 | bool emulateAbsIntFunction() const { |
210 | return false; |
211 | } |
212 | |
213 | bool rewriteDoWhileLoops() const { |
214 | return false; |
215 | } |
216 | |
217 | bool removePowWithConstantExponent() const { |
218 | return false; |
219 | } |
220 | |
221 | const char* fbFetchColorName() const { |
222 | return nullptr; |
223 | } |
224 | }; |
225 | |
226 | extern StandaloneShaderCaps standaloneCaps; |
227 | |
228 | #else |
229 | |
230 | #define SKSL_CAPS_CLASS GrShaderCaps |
231 | // Various sets of caps for use in tests |
232 | class ShaderCapsFactory { |
233 | public: |
234 | static sk_sp<GrShaderCaps> Default() { |
235 | sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions()); |
236 | result->fVersionDeclString = "#version 400" ; |
237 | result->fShaderDerivativeSupport = true; |
238 | return result; |
239 | } |
240 | |
241 | static sk_sp<GrShaderCaps> Version450Core() { |
242 | sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions()); |
243 | result->fVersionDeclString = "#version 450 core" ; |
244 | return result; |
245 | } |
246 | |
247 | static sk_sp<GrShaderCaps> Version110() { |
248 | sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions()); |
249 | result->fVersionDeclString = "#version 110" ; |
250 | result->fGLSLGeneration = GrGLSLGeneration::k110_GrGLSLGeneration; |
251 | return result; |
252 | } |
253 | |
254 | static sk_sp<GrShaderCaps> UsesPrecisionModifiers() { |
255 | sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions()); |
256 | result->fVersionDeclString = "#version 400" ; |
257 | result->fUsesPrecisionModifiers = true; |
258 | return result; |
259 | } |
260 | |
261 | static sk_sp<GrShaderCaps> CannotUseMinAndAbsTogether() { |
262 | sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions()); |
263 | result->fVersionDeclString = "#version 400" ; |
264 | result->fCanUseMinAndAbsTogether = false; |
265 | return result; |
266 | } |
267 | |
268 | static sk_sp<GrShaderCaps> CannotUseFractForNegativeValues() { |
269 | sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions()); |
270 | result->fVersionDeclString = "#version 400" ; |
271 | result->fCanUseFractForNegativeValues = false; |
272 | return result; |
273 | } |
274 | |
275 | static sk_sp<GrShaderCaps> MustForceNegatedAtanParamToFloat() { |
276 | sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions()); |
277 | result->fVersionDeclString = "#version 400" ; |
278 | result->fMustForceNegatedAtanParamToFloat = true; |
279 | return result; |
280 | } |
281 | |
282 | static sk_sp<GrShaderCaps> ShaderDerivativeExtensionString() { |
283 | sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions()); |
284 | result->fVersionDeclString = "#version 400" ; |
285 | result->fShaderDerivativeSupport = true; |
286 | result->fShaderDerivativeExtensionString = "GL_OES_standard_derivatives" ; |
287 | result->fUsesPrecisionModifiers = true; |
288 | return result; |
289 | } |
290 | |
291 | static sk_sp<GrShaderCaps> FragCoordsOld() { |
292 | sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions()); |
293 | result->fVersionDeclString = "#version 110" ; |
294 | result->fGLSLGeneration = GrGLSLGeneration::k110_GrGLSLGeneration; |
295 | result->fFragCoordConventionsExtensionString = "GL_ARB_fragment_coord_conventions" ; |
296 | return result; |
297 | } |
298 | |
299 | static sk_sp<GrShaderCaps> FragCoordsNew() { |
300 | sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions()); |
301 | result->fVersionDeclString = "#version 400" ; |
302 | result->fFragCoordConventionsExtensionString = "GL_ARB_fragment_coord_conventions" ; |
303 | return result; |
304 | } |
305 | |
306 | static sk_sp<GrShaderCaps> GeometryShaderSupport() { |
307 | sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions()); |
308 | result->fVersionDeclString = "#version 400" ; |
309 | result->fGeometryShaderSupport = true; |
310 | result->fGSInvocationsSupport = true; |
311 | return result; |
312 | } |
313 | |
314 | static sk_sp<GrShaderCaps> NoGSInvocationsSupport() { |
315 | sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions()); |
316 | result->fVersionDeclString = "#version 400" ; |
317 | result->fGeometryShaderSupport = true; |
318 | result->fGSInvocationsSupport = false; |
319 | return result; |
320 | } |
321 | |
322 | static sk_sp<GrShaderCaps> GeometryShaderExtensionString() { |
323 | sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions()); |
324 | result->fVersionDeclString = "#version 310es" ; |
325 | result->fGeometryShaderSupport = true; |
326 | result->fGeometryShaderExtensionString = "GL_EXT_geometry_shader" ; |
327 | result->fGSInvocationsSupport = true; |
328 | return result; |
329 | } |
330 | |
331 | static sk_sp<GrShaderCaps> GSInvocationsExtensionString() { |
332 | sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions()); |
333 | result->fVersionDeclString = "#version 400" ; |
334 | result->fGeometryShaderSupport = true; |
335 | result->fGSInvocationsSupport = true; |
336 | result->fGSInvocationsExtensionString = "GL_ARB_gpu_shader5" ; |
337 | return result; |
338 | } |
339 | |
340 | static sk_sp<GrShaderCaps> VariousCaps() { |
341 | sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions()); |
342 | result->fVersionDeclString = "#version 400" ; |
343 | result->fExternalTextureSupport = true; |
344 | result->fFBFetchSupport = false; |
345 | result->fCanUseAnyFunctionInShader = false; |
346 | return result; |
347 | } |
348 | |
349 | static sk_sp<GrShaderCaps> CannotUseFragCoord() { |
350 | sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions()); |
351 | result->fVersionDeclString = "#version 400" ; |
352 | result->fCanUseFragCoord = false; |
353 | return result; |
354 | } |
355 | |
356 | static sk_sp<GrShaderCaps> IncompleteShortIntPrecision() { |
357 | sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions()); |
358 | result->fVersionDeclString = "#version 310es" ; |
359 | result->fUsesPrecisionModifiers = true; |
360 | result->fIncompleteShortIntPrecision = true; |
361 | return result; |
362 | } |
363 | |
364 | static sk_sp<GrShaderCaps> AddAndTrueToLoopCondition() { |
365 | sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions()); |
366 | result->fVersionDeclString = "#version 400" ; |
367 | result->fAddAndTrueToLoopCondition = true; |
368 | return result; |
369 | } |
370 | |
371 | static sk_sp<GrShaderCaps> UnfoldShortCircuitAsTernary() { |
372 | sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions()); |
373 | result->fVersionDeclString = "#version 400" ; |
374 | result->fUnfoldShortCircuitAsTernary = true; |
375 | return result; |
376 | } |
377 | |
378 | static sk_sp<GrShaderCaps> EmulateAbsIntFunction() { |
379 | sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions()); |
380 | result->fVersionDeclString = "#version 400" ; |
381 | result->fEmulateAbsIntFunction = true; |
382 | return result; |
383 | } |
384 | |
385 | static sk_sp<GrShaderCaps> RewriteDoWhileLoops() { |
386 | sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions()); |
387 | result->fVersionDeclString = "#version 400" ; |
388 | result->fRewriteDoWhileLoops = true; |
389 | return result; |
390 | } |
391 | |
392 | static sk_sp<GrShaderCaps> RemovePowWithConstantExponent() { |
393 | sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions()); |
394 | result->fVersionDeclString = "#version 400" ; |
395 | result->fRemovePowWithConstantExponent = true; |
396 | return result; |
397 | } |
398 | |
399 | static sk_sp<GrShaderCaps> SampleMaskSupport() { |
400 | sk_sp<GrShaderCaps> result = Default(); |
401 | result->fSampleMaskSupport = true; |
402 | return result; |
403 | } |
404 | }; |
405 | #endif |
406 | |
407 | #if !defined(SKSL_STANDALONE) |
408 | bool type_to_grsltype(const Context& context, const Type& type, GrSLType* outType); |
409 | #endif |
410 | |
411 | void write_stringstream(const StringStream& d, OutputStream& out); |
412 | |
413 | // Returns true if op is '=' or any compound assignment operator ('+=', '-=', etc.) |
414 | bool is_assignment(Token::Kind op); |
415 | |
416 | // Given a compound assignment operator, returns the non-assignment version of the operator (e.g. |
417 | // '+=' becomes '+') |
418 | Token::Kind remove_assignment(Token::Kind op); |
419 | |
420 | NORETURN void sksl_abort(); |
421 | |
422 | } // namespace SkSL |
423 | |
424 | #endif |
425 | |