• 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         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 
FormatToStrLayout102     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 
ReadFormatLayout119     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 
CTypeToStrLayout154     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 
LayoutLayout190     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 
LayoutLayout209     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 
descriptionLayout225     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