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