ethannicholas | b3058bd | 2016-07-01 08:22:01 -0700 | [diff] [blame] | 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 | */ |
Ethan Nicholas | 11d5397 | 2016-11-28 11:23:23 -0500 | [diff] [blame] | 7 | |
ethannicholas | b3058bd | 2016-07-01 08:22:01 -0700 | [diff] [blame] | 8 | #ifndef SKSL_LAYOUT |
| 9 | #define SKSL_LAYOUT |
| 10 | |
Ethan Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 11 | #include "SkSLString.h" |
Ethan Nicholas | 11d5397 | 2016-11-28 11:23:23 -0500 | [diff] [blame] | 12 | #include "SkSLUtil.h" |
| 13 | |
ethannicholas | b3058bd | 2016-07-01 08:22:01 -0700 | [diff] [blame] | 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 { |
Ethan Nicholas | 39204fd | 2017-11-27 13:12:30 -0500 | [diff] [blame] | 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, |
Michael Ludwig | a427559 | 2018-08-31 10:52:47 -0400 | [diff] [blame^] | 41 | kBlendSupportHSLLuminosity_Flag = 1 << 18, |
| 42 | kTracked_Flag = 1 << 19 |
Ethan Nicholas | 39204fd | 2017-11-27 13:12:30 -0500 | [diff] [blame] | 43 | }; |
| 44 | |
Ethan Nicholas | 52cad15 | 2017-02-16 16:37:32 -0500 | [diff] [blame] | 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 | |
Ethan Nicholas | 11d5397 | 2016-11-28 11:23:23 -0500 | [diff] [blame] | 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 | }; |
| 68 | |
Ethan Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 69 | // used by SkSL processors |
| 70 | enum Key { |
| 71 | // field is not a key |
| 72 | kNo_Key, |
| 73 | // field is a key |
| 74 | kKey_Key, |
| 75 | // key is 0 or 1 depending on whether the matrix is an identity matrix |
| 76 | kIdentity_Key, |
| 77 | }; |
| 78 | |
Ethan Nicholas | 11d5397 | 2016-11-28 11:23:23 -0500 | [diff] [blame] | 79 | static const char* FormatToStr(Format format) { |
| 80 | switch (format) { |
| 81 | case Format::kUnspecified: return ""; |
| 82 | case Format::kRGBA32F: return "rgba32f"; |
| 83 | case Format::kR32F: return "r32f"; |
| 84 | case Format::kRGBA16F: return "rgba16f"; |
| 85 | case Format::kR16F: return "r16f"; |
| 86 | case Format::kRGBA8: return "rgba8"; |
| 87 | case Format::kR8: return "r8"; |
| 88 | case Format::kRGBA8I: return "rgba8i"; |
| 89 | case Format::kR8I: return "r8i"; |
| 90 | } |
Ethan Nicholas | 0df1b04 | 2017-03-31 13:56:23 -0400 | [diff] [blame] | 91 | ABORT("Unexpected format"); |
Ethan Nicholas | 11d5397 | 2016-11-28 11:23:23 -0500 | [diff] [blame] | 92 | } |
| 93 | |
Ethan Nicholas | 0df1b04 | 2017-03-31 13:56:23 -0400 | [diff] [blame] | 94 | static bool ReadFormat(String str, Format* format) { |
Ethan Nicholas | 11d5397 | 2016-11-28 11:23:23 -0500 | [diff] [blame] | 95 | if (str == "rgba32f") { |
| 96 | *format = Format::kRGBA32F; |
| 97 | return true; |
| 98 | } else if (str == "r32f") { |
| 99 | *format = Format::kR32F; |
| 100 | return true; |
| 101 | } else if (str == "rgba16f") { |
| 102 | *format = Format::kRGBA16F; |
| 103 | return true; |
| 104 | } else if (str == "r16f") { |
| 105 | *format = Format::kR16F; |
| 106 | return true; |
| 107 | } else if (str == "rgba8") { |
| 108 | *format = Format::kRGBA8; |
| 109 | return true; |
| 110 | } else if (str == "r8") { |
| 111 | *format = Format::kR8; |
| 112 | return true; |
| 113 | } else if (str == "rgba8i") { |
| 114 | *format = Format::kRGBA8I; |
| 115 | return true; |
| 116 | } else if (str == "r8i") { |
| 117 | *format = Format::kR8I; |
| 118 | return true; |
| 119 | } |
| 120 | return false; |
| 121 | } |
ethannicholas | b3058bd | 2016-07-01 08:22:01 -0700 | [diff] [blame] | 122 | |
Ethan Nicholas | 39204fd | 2017-11-27 13:12:30 -0500 | [diff] [blame] | 123 | Layout(int flags, int location, int offset, int binding, int index, int set, int builtin, |
| 124 | int inputAttachmentIndex, Format format, Primitive primitive, int maxVertices, |
| 125 | int invocations, String when, Key key, StringFragment ctype) |
| 126 | : fFlags(flags) |
| 127 | , fLocation(location) |
Ethan Nicholas | 1967177 | 2016-11-28 16:30:17 -0500 | [diff] [blame] | 128 | , fOffset(offset) |
ethannicholas | b3058bd | 2016-07-01 08:22:01 -0700 | [diff] [blame] | 129 | , fBinding(binding) |
| 130 | , fIndex(index) |
| 131 | , fSet(set) |
ethannicholas | f789b38 | 2016-08-03 12:43:36 -0700 | [diff] [blame] | 132 | , fBuiltin(builtin) |
Greg Daniel | 64773e6 | 2016-11-22 09:44:03 -0500 | [diff] [blame] | 133 | , fInputAttachmentIndex(inputAttachmentIndex) |
ethannicholas | 8ac838d | 2016-11-22 08:39:36 -0800 | [diff] [blame] | 134 | , fFormat(format) |
Ethan Nicholas | 52cad15 | 2017-02-16 16:37:32 -0500 | [diff] [blame] | 135 | , fPrimitive(primitive) |
| 136 | , fMaxVertices(maxVertices) |
Ethan Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 137 | , fInvocations(invocations) |
| 138 | , fWhen(when) |
Ethan Nicholas | d608c09 | 2017-10-26 09:30:08 -0400 | [diff] [blame] | 139 | , fKey(key) |
| 140 | , fCType(ctype) {} |
Brian Salomon | 2a51de8 | 2016-11-16 12:06:01 -0500 | [diff] [blame] | 141 | |
Greg Daniel | 64773e6 | 2016-11-22 09:44:03 -0500 | [diff] [blame] | 142 | Layout() |
Ethan Nicholas | 39204fd | 2017-11-27 13:12:30 -0500 | [diff] [blame] | 143 | : fFlags(0) |
| 144 | , fLocation(-1) |
Ethan Nicholas | 1967177 | 2016-11-28 16:30:17 -0500 | [diff] [blame] | 145 | , fOffset(-1) |
Brian Salomon | 2a51de8 | 2016-11-16 12:06:01 -0500 | [diff] [blame] | 146 | , fBinding(-1) |
| 147 | , fIndex(-1) |
| 148 | , fSet(-1) |
| 149 | , fBuiltin(-1) |
Greg Daniel | 64773e6 | 2016-11-22 09:44:03 -0500 | [diff] [blame] | 150 | , fInputAttachmentIndex(-1) |
Ethan Nicholas | 11d5397 | 2016-11-28 11:23:23 -0500 | [diff] [blame] | 151 | , fFormat(Format::kUnspecified) |
Ethan Nicholas | 52cad15 | 2017-02-16 16:37:32 -0500 | [diff] [blame] | 152 | , fPrimitive(kUnspecified_Primitive) |
| 153 | , fMaxVertices(-1) |
Ethan Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 154 | , fInvocations(-1) |
| 155 | , fKey(kNo_Key) {} |
ethannicholas | b3058bd | 2016-07-01 08:22:01 -0700 | [diff] [blame] | 156 | |
Ethan Nicholas | 0df1b04 | 2017-03-31 13:56:23 -0400 | [diff] [blame] | 157 | String description() const { |
| 158 | String result; |
| 159 | String separator; |
ethannicholas | b3058bd | 2016-07-01 08:22:01 -0700 | [diff] [blame] | 160 | if (fLocation >= 0) { |
| 161 | result += separator + "location = " + to_string(fLocation); |
| 162 | separator = ", "; |
| 163 | } |
Ethan Nicholas | 1967177 | 2016-11-28 16:30:17 -0500 | [diff] [blame] | 164 | if (fOffset >= 0) { |
| 165 | result += separator + "offset = " + to_string(fOffset); |
| 166 | separator = ", "; |
| 167 | } |
ethannicholas | b3058bd | 2016-07-01 08:22:01 -0700 | [diff] [blame] | 168 | if (fBinding >= 0) { |
| 169 | result += separator + "binding = " + to_string(fBinding); |
| 170 | separator = ", "; |
| 171 | } |
| 172 | if (fIndex >= 0) { |
| 173 | result += separator + "index = " + to_string(fIndex); |
| 174 | separator = ", "; |
| 175 | } |
| 176 | if (fSet >= 0) { |
| 177 | result += separator + "set = " + to_string(fSet); |
| 178 | separator = ", "; |
| 179 | } |
| 180 | if (fBuiltin >= 0) { |
| 181 | result += separator + "builtin = " + to_string(fBuiltin); |
| 182 | separator = ", "; |
| 183 | } |
Greg Daniel | 64773e6 | 2016-11-22 09:44:03 -0500 | [diff] [blame] | 184 | if (fInputAttachmentIndex >= 0) { |
z102.zhang | 937efc3 | 2018-08-17 11:15:27 +0800 | [diff] [blame] | 185 | result += separator + "input_attachment_index = " + to_string(fInputAttachmentIndex); |
Greg Daniel | 64773e6 | 2016-11-22 09:44:03 -0500 | [diff] [blame] | 186 | separator = ", "; |
| 187 | } |
Ethan Nicholas | 11d5397 | 2016-11-28 11:23:23 -0500 | [diff] [blame] | 188 | if (Format::kUnspecified != fFormat) { |
| 189 | result += separator + FormatToStr(fFormat); |
Brian Salomon | 2a51de8 | 2016-11-16 12:06:01 -0500 | [diff] [blame] | 190 | separator = ", "; |
| 191 | } |
Ethan Nicholas | 39204fd | 2017-11-27 13:12:30 -0500 | [diff] [blame] | 192 | if (fFlags & kOriginUpperLeft_Flag) { |
| 193 | result += separator + "origin_upper_left"; |
| 194 | separator = ", "; |
| 195 | } |
| 196 | if (fFlags & kOverrideCoverage_Flag) { |
| 197 | result += separator + "override_coverage"; |
| 198 | separator = ", "; |
| 199 | } |
| 200 | if (fFlags & kBlendSupportAllEquations_Flag) { |
| 201 | result += separator + "blend_support_all_equations"; |
| 202 | separator = ", "; |
| 203 | } |
| 204 | if (fFlags & kBlendSupportMultiply_Flag) { |
| 205 | result += separator + "blend_support_multiply"; |
| 206 | separator = ", "; |
| 207 | } |
| 208 | if (fFlags & kBlendSupportScreen_Flag) { |
| 209 | result += separator + "blend_support_screen"; |
| 210 | separator = ", "; |
| 211 | } |
| 212 | if (fFlags & kBlendSupportOverlay_Flag) { |
| 213 | result += separator + "blend_support_overlay"; |
| 214 | separator = ", "; |
| 215 | } |
| 216 | if (fFlags & kBlendSupportDarken_Flag) { |
| 217 | result += separator + "blend_support_darken"; |
| 218 | separator = ", "; |
| 219 | } |
| 220 | if (fFlags & kBlendSupportLighten_Flag) { |
| 221 | result += separator + "blend_support_lighten"; |
| 222 | separator = ", "; |
| 223 | } |
| 224 | if (fFlags & kBlendSupportColorDodge_Flag) { |
| 225 | result += separator + "blend_support_colordodge"; |
| 226 | separator = ", "; |
| 227 | } |
| 228 | if (fFlags & kBlendSupportColorBurn_Flag) { |
| 229 | result += separator + "blend_support_colorburn"; |
| 230 | separator = ", "; |
| 231 | } |
| 232 | if (fFlags & kBlendSupportHardLight_Flag) { |
| 233 | result += separator + "blend_support_hardlight"; |
| 234 | separator = ", "; |
| 235 | } |
| 236 | if (fFlags & kBlendSupportSoftLight_Flag) { |
| 237 | result += separator + "blend_support_softlight"; |
| 238 | separator = ", "; |
| 239 | } |
| 240 | if (fFlags & kBlendSupportDifference_Flag) { |
| 241 | result += separator + "blend_support_difference"; |
| 242 | separator = ", "; |
| 243 | } |
| 244 | if (fFlags & kBlendSupportExclusion_Flag) { |
| 245 | result += separator + "blend_support_exclusion"; |
| 246 | separator = ", "; |
| 247 | } |
| 248 | if (fFlags & kBlendSupportHSLHue_Flag) { |
| 249 | result += separator + "blend_support_hsl_hue"; |
| 250 | separator = ", "; |
| 251 | } |
| 252 | if (fFlags & kBlendSupportHSLSaturation_Flag) { |
| 253 | result += separator + "blend_support_hsl_saturation"; |
| 254 | separator = ", "; |
| 255 | } |
| 256 | if (fFlags & kBlendSupportHSLColor_Flag) { |
| 257 | result += separator + "blend_support_hsl_color"; |
| 258 | separator = ", "; |
| 259 | } |
| 260 | if (fFlags & kBlendSupportHSLLuminosity_Flag) { |
| 261 | result += separator + "blend_support_hsl_luminosity"; |
| 262 | separator = ", "; |
| 263 | } |
| 264 | if (fFlags & kPushConstant_Flag) { |
ethannicholas | 8ac838d | 2016-11-22 08:39:36 -0800 | [diff] [blame] | 265 | result += separator + "push_constant"; |
| 266 | separator = ", "; |
| 267 | } |
Michael Ludwig | a427559 | 2018-08-31 10:52:47 -0400 | [diff] [blame^] | 268 | if (fFlags & kTracked_Flag) { |
| 269 | result += separator + "tracked"; |
| 270 | separator = ", "; |
| 271 | } |
Ethan Nicholas | 52cad15 | 2017-02-16 16:37:32 -0500 | [diff] [blame] | 272 | switch (fPrimitive) { |
| 273 | case kPoints_Primitive: |
| 274 | result += separator + "points"; |
| 275 | separator = ", "; |
| 276 | break; |
| 277 | case kLines_Primitive: |
| 278 | result += separator + "lines"; |
| 279 | separator = ", "; |
| 280 | break; |
| 281 | case kLineStrip_Primitive: |
| 282 | result += separator + "line_strip"; |
| 283 | separator = ", "; |
| 284 | break; |
| 285 | case kLinesAdjacency_Primitive: |
| 286 | result += separator + "lines_adjacency"; |
| 287 | separator = ", "; |
| 288 | break; |
| 289 | case kTriangles_Primitive: |
| 290 | result += separator + "triangles"; |
| 291 | separator = ", "; |
| 292 | break; |
| 293 | case kTriangleStrip_Primitive: |
| 294 | result += separator + "triangle_strip"; |
| 295 | separator = ", "; |
| 296 | break; |
| 297 | case kTrianglesAdjacency_Primitive: |
| 298 | result += separator + "triangles_adjacency"; |
| 299 | separator = ", "; |
| 300 | break; |
| 301 | case kUnspecified_Primitive: |
| 302 | break; |
| 303 | } |
| 304 | if (fMaxVertices >= 0) { |
| 305 | result += separator + "max_vertices = " + to_string(fMaxVertices); |
| 306 | separator = ", "; |
| 307 | } |
| 308 | if (fInvocations >= 0) { |
| 309 | result += separator + "invocations = " + to_string(fInvocations); |
| 310 | separator = ", "; |
| 311 | } |
Ethan Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 312 | if (fWhen.size()) { |
| 313 | result += separator + "when = " + fWhen; |
| 314 | separator = ", "; |
| 315 | } |
Ethan Nicholas | 9e1138d | 2016-11-21 10:39:35 -0500 | [diff] [blame] | 316 | if (result.size() > 0) { |
ethannicholas | b3058bd | 2016-07-01 08:22:01 -0700 | [diff] [blame] | 317 | result = "layout (" + result + ")"; |
| 318 | } |
Ethan Nicholas | 0054311 | 2018-07-31 09:44:36 -0400 | [diff] [blame] | 319 | if (fKey) { |
| 320 | result += "/* key */"; |
| 321 | } |
ethannicholas | b3058bd | 2016-07-01 08:22:01 -0700 | [diff] [blame] | 322 | return result; |
| 323 | } |
| 324 | |
| 325 | bool operator==(const Layout& other) const { |
Ethan Nicholas | 39204fd | 2017-11-27 13:12:30 -0500 | [diff] [blame] | 326 | return fFlags == other.fFlags && |
| 327 | fLocation == other.fLocation && |
| 328 | fOffset == other.fOffset && |
| 329 | fBinding == other.fBinding && |
| 330 | fIndex == other.fIndex && |
| 331 | fSet == other.fSet && |
| 332 | fBuiltin == other.fBuiltin && |
| 333 | fInputAttachmentIndex == other.fInputAttachmentIndex && |
| 334 | fFormat == other.fFormat && |
| 335 | fPrimitive == other.fPrimitive && |
| 336 | fMaxVertices == other.fMaxVertices && |
| 337 | fInvocations == other.fInvocations; |
ethannicholas | b3058bd | 2016-07-01 08:22:01 -0700 | [diff] [blame] | 338 | } |
| 339 | |
| 340 | bool operator!=(const Layout& other) const { |
| 341 | return !(*this == other); |
| 342 | } |
| 343 | |
Ethan Nicholas | 39204fd | 2017-11-27 13:12:30 -0500 | [diff] [blame] | 344 | int fFlags; |
ethannicholas | f789b38 | 2016-08-03 12:43:36 -0700 | [diff] [blame] | 345 | int fLocation; |
Ethan Nicholas | 1967177 | 2016-11-28 16:30:17 -0500 | [diff] [blame] | 346 | int fOffset; |
ethannicholas | f789b38 | 2016-08-03 12:43:36 -0700 | [diff] [blame] | 347 | int fBinding; |
| 348 | int fIndex; |
| 349 | int fSet; |
Greg Daniel | 64773e6 | 2016-11-22 09:44:03 -0500 | [diff] [blame] | 350 | // builtin comes from SPIR-V and identifies which particular builtin value this object |
| 351 | // represents. |
ethannicholas | f789b38 | 2016-08-03 12:43:36 -0700 | [diff] [blame] | 352 | int fBuiltin; |
Greg Daniel | 64773e6 | 2016-11-22 09:44:03 -0500 | [diff] [blame] | 353 | // input_attachment_index comes from Vulkan/SPIR-V to connect a shader variable to the a |
| 354 | // corresponding attachment on the subpass in which the shader is being used. |
| 355 | int fInputAttachmentIndex; |
Ethan Nicholas | 11d5397 | 2016-11-28 11:23:23 -0500 | [diff] [blame] | 356 | Format fFormat; |
Ethan Nicholas | 52cad15 | 2017-02-16 16:37:32 -0500 | [diff] [blame] | 357 | Primitive fPrimitive; |
| 358 | int fMaxVertices; |
| 359 | int fInvocations; |
Ethan Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 360 | String fWhen; |
| 361 | Key fKey; |
Ethan Nicholas | d608c09 | 2017-10-26 09:30:08 -0400 | [diff] [blame] | 362 | StringFragment fCType; |
ethannicholas | b3058bd | 2016-07-01 08:22:01 -0700 | [diff] [blame] | 363 | }; |
| 364 | |
| 365 | } // namespace |
| 366 | |
| 367 | #endif |