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
14namespace SkSL {
15
16/**
17 * Represents a layout block appearing before a variable declaration, as in:
18 *
19 * layout (location = 0) int x;
20 */
21struct 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