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_LAYOUT |
9 | #define SKSL_LAYOUT |
10 | |
11 | #include "src/sksl/SkSLString.h" |
12 | #include "src/sksl/SkSLUtil.h" |
13 | |
14 | namespace SkSL { |
15 | |
16 | /** |
17 | * Represents a layout block appearing before a variable declaration, as in: |
18 | * |
19 | * layout (location = 0) int x; |
20 | */ |
21 | struct Layout { |
22 | enum Flag { |
23 | kOriginUpperLeft_Flag = 1 << 0, |
24 | kOverrideCoverage_Flag = 1 << 1, |
25 | kPushConstant_Flag = 1 << 2, |
26 | kBlendSupportAllEquations_Flag = 1 << 3, |
27 | kBlendSupportMultiply_Flag = 1 << 4, |
28 | kBlendSupportScreen_Flag = 1 << 5, |
29 | kBlendSupportOverlay_Flag = 1 << 6, |
30 | kBlendSupportDarken_Flag = 1 << 7, |
31 | kBlendSupportLighten_Flag = 1 << 8, |
32 | kBlendSupportColorDodge_Flag = 1 << 9, |
33 | kBlendSupportColorBurn_Flag = 1 << 10, |
34 | kBlendSupportHardLight_Flag = 1 << 11, |
35 | kBlendSupportSoftLight_Flag = 1 << 12, |
36 | kBlendSupportDifference_Flag = 1 << 13, |
37 | kBlendSupportExclusion_Flag = 1 << 14, |
38 | kBlendSupportHSLHue_Flag = 1 << 15, |
39 | kBlendSupportHSLSaturation_Flag = 1 << 16, |
40 | kBlendSupportHSLColor_Flag = 1 << 17, |
41 | kBlendSupportHSLLuminosity_Flag = 1 << 18, |
42 | kTracked_Flag = 1 << 19, |
43 | kSRGBUnpremul_Flag = 1 << 20, |
44 | }; |
45 | |
46 | enum Primitive { |
47 | kUnspecified_Primitive = -1, |
48 | kPoints_Primitive, |
49 | kLines_Primitive, |
50 | kLineStrip_Primitive, |
51 | kLinesAdjacency_Primitive, |
52 | kTriangles_Primitive, |
53 | kTriangleStrip_Primitive, |
54 | kTrianglesAdjacency_Primitive |
55 | }; |
56 | |
57 | // These are used by images in GLSL. We only support a subset of what GL supports. |
58 | enum class Format { |
59 | kUnspecified = -1, |
60 | kRGBA32F, |
61 | kR32F, |
62 | kRGBA16F, |
63 | kR16F, |
64 | kLUMINANCE16F, |
65 | kRGBA8, |
66 | kR8, |
67 | kRGBA8I, |
68 | kR8I, |
69 | kRG16F, |
70 | }; |
71 | |
72 | // used by SkSL processors |
73 | enum Key { |
74 | // field is not a key |
75 | kNo_Key, |
76 | // field is a key |
77 | kKey_Key, |
78 | // key is 0 or 1 depending on whether the matrix is an identity matrix |
79 | kIdentity_Key, |
80 | }; |
81 | |
82 | enum class CType { |
83 | kDefault, |
84 | kBool, |
85 | kFloat, |
86 | kFloat2, |
87 | kFloat3, |
88 | kFloat4, |
89 | kInt32, |
90 | kSkRect, |
91 | kSkIRect, |
92 | kSkPMColor4f, |
93 | kSkPMColor, |
94 | kSkV4, |
95 | kSkPoint, |
96 | kSkIPoint, |
97 | kSkMatrix, |
98 | kSkM44, |
99 | kGrSurfaceProxyView, |
100 | kGrFragmentProcessor, |
101 | }; |
102 | |
103 | static const char* FormatToStr(Format format) { |
104 | switch (format) { |
105 | case Format::kUnspecified: return "" ; |
106 | case Format::kRGBA32F: return "rgba32f" ; |
107 | case Format::kR32F: return "r32f" ; |
108 | case Format::kRGBA16F: return "rgba16f" ; |
109 | case Format::kR16F: return "r16f" ; |
110 | case Format::kLUMINANCE16F: return "lum16f" ; |
111 | case Format::kRGBA8: return "rgba8" ; |
112 | case Format::kR8: return "r8" ; |
113 | case Format::kRGBA8I: return "rgba8i" ; |
114 | case Format::kR8I: return "r8i" ; |
115 | case Format::kRG16F: return "rg16f" ; |
116 | } |
117 | ABORT("Unexpected format" ); |
118 | } |
119 | |
120 | static bool ReadFormat(String str, Format* format) { |
121 | if (str == "rgba32f" ) { |
122 | *format = Format::kRGBA32F; |
123 | return true; |
124 | } else if (str == "r32f" ) { |
125 | *format = Format::kR32F; |
126 | return true; |
127 | } else if (str == "rgba16f" ) { |
128 | *format = Format::kRGBA16F; |
129 | return true; |
130 | } else if (str == "r16f" ) { |
131 | *format = Format::kR16F; |
132 | return true; |
133 | } else if (str == "lum16f" ) { |
134 | *format = Format::kLUMINANCE16F; |
135 | return true; |
136 | } else if (str == "rgba8" ) { |
137 | *format = Format::kRGBA8; |
138 | return true; |
139 | } else if (str == "r8" ) { |
140 | *format = Format::kR8; |
141 | return true; |
142 | } else if (str == "rgba8i" ) { |
143 | *format = Format::kRGBA8I; |
144 | return true; |
145 | } else if (str == "r8i" ) { |
146 | *format = Format::kR8I; |
147 | return true; |
148 | } else if (str == "rg16f" ) { |
149 | *format = Format::kRG16F; |
150 | return true; |
151 | } |
152 | return false; |
153 | } |
154 | |
155 | static const char* CTypeToStr(CType ctype) { |
156 | switch (ctype) { |
157 | case CType::kDefault: |
158 | return nullptr; |
159 | case CType::kFloat: |
160 | return "float" ; |
161 | case CType::kInt32: |
162 | return "int32_t" ; |
163 | case CType::kSkRect: |
164 | return "SkRect" ; |
165 | case CType::kSkIRect: |
166 | return "SkIRect" ; |
167 | case CType::kSkPMColor4f: |
168 | return "SkPMColor4f" ; |
169 | case CType::kSkPMColor: |
170 | return "SkPMColor" ; |
171 | case CType::kSkV4: |
172 | return "SkV4" ; |
173 | case CType::kSkPoint: |
174 | return "SkPoint" ; |
175 | case CType::kSkIPoint: |
176 | return "SkIPoint" ; |
177 | case CType::kSkMatrix: |
178 | return "SkMatrix" ; |
179 | case CType::kSkM44: |
180 | return "SkM44" ; |
181 | case CType::kGrSurfaceProxyView: |
182 | return "GrSurfaceProxyView" ; |
183 | case CType::kGrFragmentProcessor: |
184 | return "std::unique_ptr<GrFragmentProcessor>" ; |
185 | default: |
186 | SkASSERT(false); |
187 | return nullptr; |
188 | } |
189 | } |
190 | |
191 | Layout(int flags, int location, int offset, int binding, int index, int set, int builtin, |
192 | int inputAttachmentIndex, Format format, Primitive primitive, int maxVertices, |
193 | int invocations, StringFragment marker, StringFragment when, Key key, CType ctype) |
194 | : fFlags(flags) |
195 | , fLocation(location) |
196 | , fOffset(offset) |
197 | , fBinding(binding) |
198 | , fIndex(index) |
199 | , fSet(set) |
200 | , fBuiltin(builtin) |
201 | , fInputAttachmentIndex(inputAttachmentIndex) |
202 | , fFormat(format) |
203 | , fPrimitive(primitive) |
204 | , fMaxVertices(maxVertices) |
205 | , fInvocations(invocations) |
206 | , fMarker(marker) |
207 | , fWhen(when) |
208 | , fKey(key) |
209 | , fCType(ctype) {} |
210 | |
211 | Layout() |
212 | : fFlags(0) |
213 | , fLocation(-1) |
214 | , fOffset(-1) |
215 | , fBinding(-1) |
216 | , fIndex(-1) |
217 | , fSet(-1) |
218 | , fBuiltin(-1) |
219 | , fInputAttachmentIndex(-1) |
220 | , fFormat(Format::kUnspecified) |
221 | , fPrimitive(kUnspecified_Primitive) |
222 | , fMaxVertices(-1) |
223 | , fInvocations(-1) |
224 | , fKey(kNo_Key) |
225 | , fCType(CType::kDefault) {} |
226 | |
227 | static Layout builtin(int builtin) { |
228 | Layout result; |
229 | result.fBuiltin = builtin; |
230 | return result; |
231 | } |
232 | |
233 | String description() const { |
234 | String result; |
235 | auto separator = [firstSeparator = true]() mutable -> String { |
236 | if (firstSeparator) { |
237 | firstSeparator = false; |
238 | return "" ; |
239 | } else { |
240 | return ", " ; |
241 | }}; |
242 | if (fLocation >= 0) { |
243 | result += separator() + "location = " + to_string(fLocation); |
244 | } |
245 | if (fOffset >= 0) { |
246 | result += separator() + "offset = " + to_string(fOffset); |
247 | } |
248 | if (fBinding >= 0) { |
249 | result += separator() + "binding = " + to_string(fBinding); |
250 | } |
251 | if (fIndex >= 0) { |
252 | result += separator() + "index = " + to_string(fIndex); |
253 | } |
254 | if (fSet >= 0) { |
255 | result += separator() + "set = " + to_string(fSet); |
256 | } |
257 | if (fBuiltin >= 0) { |
258 | result += separator() + "builtin = " + to_string(fBuiltin); |
259 | } |
260 | if (fInputAttachmentIndex >= 0) { |
261 | result += separator() + "input_attachment_index = " + to_string(fInputAttachmentIndex); |
262 | } |
263 | if (Format::kUnspecified != fFormat) { |
264 | result += separator() + FormatToStr(fFormat); |
265 | } |
266 | if (fFlags & kOriginUpperLeft_Flag) { |
267 | result += separator() + "origin_upper_left" ; |
268 | } |
269 | if (fFlags & kOverrideCoverage_Flag) { |
270 | result += separator() + "override_coverage" ; |
271 | } |
272 | if (fFlags & kBlendSupportAllEquations_Flag) { |
273 | result += separator() + "blend_support_all_equations" ; |
274 | } |
275 | if (fFlags & kBlendSupportMultiply_Flag) { |
276 | result += separator() + "blend_support_multiply" ; |
277 | } |
278 | if (fFlags & kBlendSupportScreen_Flag) { |
279 | result += separator() + "blend_support_screen" ; |
280 | } |
281 | if (fFlags & kBlendSupportOverlay_Flag) { |
282 | result += separator() + "blend_support_overlay" ; |
283 | } |
284 | if (fFlags & kBlendSupportDarken_Flag) { |
285 | result += separator() + "blend_support_darken" ; |
286 | } |
287 | if (fFlags & kBlendSupportLighten_Flag) { |
288 | result += separator() + "blend_support_lighten" ; |
289 | } |
290 | if (fFlags & kBlendSupportColorDodge_Flag) { |
291 | result += separator() + "blend_support_colordodge" ; |
292 | } |
293 | if (fFlags & kBlendSupportColorBurn_Flag) { |
294 | result += separator() + "blend_support_colorburn" ; |
295 | } |
296 | if (fFlags & kBlendSupportHardLight_Flag) { |
297 | result += separator() + "blend_support_hardlight" ; |
298 | } |
299 | if (fFlags & kBlendSupportSoftLight_Flag) { |
300 | result += separator() + "blend_support_softlight" ; |
301 | } |
302 | if (fFlags & kBlendSupportDifference_Flag) { |
303 | result += separator() + "blend_support_difference" ; |
304 | } |
305 | if (fFlags & kBlendSupportExclusion_Flag) { |
306 | result += separator() + "blend_support_exclusion" ; |
307 | } |
308 | if (fFlags & kBlendSupportHSLHue_Flag) { |
309 | result += separator() + "blend_support_hsl_hue" ; |
310 | } |
311 | if (fFlags & kBlendSupportHSLSaturation_Flag) { |
312 | result += separator() + "blend_support_hsl_saturation" ; |
313 | } |
314 | if (fFlags & kBlendSupportHSLColor_Flag) { |
315 | result += separator() + "blend_support_hsl_color" ; |
316 | } |
317 | if (fFlags & kBlendSupportHSLLuminosity_Flag) { |
318 | result += separator() + "blend_support_hsl_luminosity" ; |
319 | } |
320 | if (fFlags & kPushConstant_Flag) { |
321 | result += separator() + "push_constant" ; |
322 | } |
323 | if (fFlags & kTracked_Flag) { |
324 | result += separator() + "tracked" ; |
325 | } |
326 | if (fFlags & kSRGBUnpremul_Flag) { |
327 | result += separator() + "srgb_unpremul" ; |
328 | } |
329 | switch (fPrimitive) { |
330 | case kPoints_Primitive: |
331 | result += separator() + "points" ; |
332 | break; |
333 | case kLines_Primitive: |
334 | result += separator() + "lines" ; |
335 | break; |
336 | case kLineStrip_Primitive: |
337 | result += separator() + "line_strip" ; |
338 | break; |
339 | case kLinesAdjacency_Primitive: |
340 | result += separator() + "lines_adjacency" ; |
341 | break; |
342 | case kTriangles_Primitive: |
343 | result += separator() + "triangles" ; |
344 | break; |
345 | case kTriangleStrip_Primitive: |
346 | result += separator() + "triangle_strip" ; |
347 | break; |
348 | case kTrianglesAdjacency_Primitive: |
349 | result += separator() + "triangles_adjacency" ; |
350 | break; |
351 | case kUnspecified_Primitive: |
352 | break; |
353 | } |
354 | if (fMaxVertices >= 0) { |
355 | result += separator() + "max_vertices = " + to_string(fMaxVertices); |
356 | } |
357 | if (fInvocations >= 0) { |
358 | result += separator() + "invocations = " + to_string(fInvocations); |
359 | } |
360 | if (fMarker.fLength) { |
361 | result += separator() + "marker = " + fMarker; |
362 | } |
363 | if (fWhen.fLength) { |
364 | result += separator() + "when = " + fWhen; |
365 | } |
366 | if (result.size() > 0) { |
367 | result = "layout (" + result + ")" ; |
368 | } |
369 | if (fKey) { |
370 | result += "/* key */" ; |
371 | } |
372 | return result; |
373 | } |
374 | |
375 | bool operator==(const Layout& other) const { |
376 | return fFlags == other.fFlags && |
377 | fLocation == other.fLocation && |
378 | fOffset == other.fOffset && |
379 | fBinding == other.fBinding && |
380 | fIndex == other.fIndex && |
381 | fSet == other.fSet && |
382 | fBuiltin == other.fBuiltin && |
383 | fInputAttachmentIndex == other.fInputAttachmentIndex && |
384 | fFormat == other.fFormat && |
385 | fPrimitive == other.fPrimitive && |
386 | fMaxVertices == other.fMaxVertices && |
387 | fInvocations == other.fInvocations && |
388 | fMarker == other.fMarker && |
389 | fWhen == other.fWhen && |
390 | fKey == other.fKey && |
391 | fCType == other.fCType; |
392 | } |
393 | |
394 | bool operator!=(const Layout& other) const { |
395 | return !(*this == other); |
396 | } |
397 | |
398 | int fFlags; |
399 | int fLocation; |
400 | int fOffset; |
401 | int fBinding; |
402 | int fIndex; |
403 | int fSet; |
404 | // builtin comes from SPIR-V and identifies which particular builtin value this object |
405 | // represents. |
406 | int fBuiltin; |
407 | // input_attachment_index comes from Vulkan/SPIR-V to connect a shader variable to the a |
408 | // corresponding attachment on the subpass in which the shader is being used. |
409 | int fInputAttachmentIndex; |
410 | Format fFormat; |
411 | Primitive fPrimitive; |
412 | int fMaxVertices; |
413 | int fInvocations; |
414 | // marker refers to matrices tagged on the SkCanvas with markCTM |
415 | StringFragment fMarker; |
416 | StringFragment fWhen; |
417 | Key fKey; |
418 | CType fCType; |
419 | }; |
420 | |
421 | } // namespace SkSL |
422 | |
423 | #endif |
424 | |