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