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