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 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 }; 43 44 enum Primitive { 45 kUnspecified_Primitive = -1, 46 kPoints_Primitive, 47 kLines_Primitive, 48 kLineStrip_Primitive, 49 kLinesAdjacency_Primitive, 50 kTriangles_Primitive, 51 kTriangleStrip_Primitive, 52 kTrianglesAdjacency_Primitive 53 }; 54 55 // These are used by images in GLSL. We only support a subset of what GL supports. 56 enum class Format { 57 kUnspecified = -1, 58 kRGBA32F, 59 kR32F, 60 kRGBA16F, 61 kR16F, 62 kRGBA8, 63 kR8, 64 kRGBA8I, 65 kR8I, 66 }; 67 68 // used by SkSL processors 69 enum Key { 70 // field is not a key 71 kNo_Key, 72 // field is a key 73 kKey_Key, 74 // key is 0 or 1 depending on whether the matrix is an identity matrix 75 kIdentity_Key, 76 }; 77 78 static const char* FormatToStr(Format format) { 79 switch (format) { 80 case Format::kUnspecified: return ""; 81 case Format::kRGBA32F: return "rgba32f"; 82 case Format::kR32F: return "r32f"; 83 case Format::kRGBA16F: return "rgba16f"; 84 case Format::kR16F: return "r16f"; 85 case Format::kRGBA8: return "rgba8"; 86 case Format::kR8: return "r8"; 87 case Format::kRGBA8I: return "rgba8i"; 88 case Format::kR8I: return "r8i"; 89 } 90 ABORT("Unexpected format"); 91 } 92 93 static bool ReadFormat(String str, Format* format) { 94 if (str == "rgba32f") { 95 *format = Format::kRGBA32F; 96 return true; 97 } else if (str == "r32f") { 98 *format = Format::kR32F; 99 return true; 100 } else if (str == "rgba16f") { 101 *format = Format::kRGBA16F; 102 return true; 103 } else if (str == "r16f") { 104 *format = Format::kR16F; 105 return true; 106 } else if (str == "rgba8") { 107 *format = Format::kRGBA8; 108 return true; 109 } else if (str == "r8") { 110 *format = Format::kR8; 111 return true; 112 } else if (str == "rgba8i") { 113 *format = Format::kRGBA8I; 114 return true; 115 } else if (str == "r8i") { 116 *format = Format::kR8I; 117 return true; 118 } 119 return false; 120 } 121 122 Layout(int flags, int location, int offset, int binding, int index, int set, int builtin, 123 int inputAttachmentIndex, Format format, Primitive primitive, int maxVertices, 124 int invocations, String when, Key key, StringFragment ctype) 125 : fFlags(flags) 126 , fLocation(location) 127 , fOffset(offset) 128 , fBinding(binding) 129 , fIndex(index) 130 , fSet(set) 131 , fBuiltin(builtin) 132 , fInputAttachmentIndex(inputAttachmentIndex) 133 , fFormat(format) 134 , fPrimitive(primitive) 135 , fMaxVertices(maxVertices) 136 , fInvocations(invocations) 137 , fWhen(when) 138 , fKey(key) 139 , fCType(ctype) {} 140 141 Layout() 142 : fFlags(0) 143 , fLocation(-1) 144 , fOffset(-1) 145 , fBinding(-1) 146 , fIndex(-1) 147 , fSet(-1) 148 , fBuiltin(-1) 149 , fInputAttachmentIndex(-1) 150 , fFormat(Format::kUnspecified) 151 , fPrimitive(kUnspecified_Primitive) 152 , fMaxVertices(-1) 153 , fInvocations(-1) 154 , fKey(kNo_Key) {} 155 156 String description() const { 157 String result; 158 String separator; 159 if (fLocation >= 0) { 160 result += separator + "location = " + to_string(fLocation); 161 separator = ", "; 162 } 163 if (fOffset >= 0) { 164 result += separator + "offset = " + to_string(fOffset); 165 separator = ", "; 166 } 167 if (fBinding >= 0) { 168 result += separator + "binding = " + to_string(fBinding); 169 separator = ", "; 170 } 171 if (fIndex >= 0) { 172 result += separator + "index = " + to_string(fIndex); 173 separator = ", "; 174 } 175 if (fSet >= 0) { 176 result += separator + "set = " + to_string(fSet); 177 separator = ", "; 178 } 179 if (fBuiltin >= 0) { 180 result += separator + "builtin = " + to_string(fBuiltin); 181 separator = ", "; 182 } 183 if (fInputAttachmentIndex >= 0) { 184 result += separator + "input_attachment_index = " + to_string(fBuiltin); 185 separator = ", "; 186 } 187 if (Format::kUnspecified != fFormat) { 188 result += separator + FormatToStr(fFormat); 189 separator = ", "; 190 } 191 if (fFlags & kOriginUpperLeft_Flag) { 192 result += separator + "origin_upper_left"; 193 separator = ", "; 194 } 195 if (fFlags & kOverrideCoverage_Flag) { 196 result += separator + "override_coverage"; 197 separator = ", "; 198 } 199 if (fFlags & kBlendSupportAllEquations_Flag) { 200 result += separator + "blend_support_all_equations"; 201 separator = ", "; 202 } 203 if (fFlags & kBlendSupportMultiply_Flag) { 204 result += separator + "blend_support_multiply"; 205 separator = ", "; 206 } 207 if (fFlags & kBlendSupportScreen_Flag) { 208 result += separator + "blend_support_screen"; 209 separator = ", "; 210 } 211 if (fFlags & kBlendSupportOverlay_Flag) { 212 result += separator + "blend_support_overlay"; 213 separator = ", "; 214 } 215 if (fFlags & kBlendSupportDarken_Flag) { 216 result += separator + "blend_support_darken"; 217 separator = ", "; 218 } 219 if (fFlags & kBlendSupportLighten_Flag) { 220 result += separator + "blend_support_lighten"; 221 separator = ", "; 222 } 223 if (fFlags & kBlendSupportColorDodge_Flag) { 224 result += separator + "blend_support_colordodge"; 225 separator = ", "; 226 } 227 if (fFlags & kBlendSupportColorBurn_Flag) { 228 result += separator + "blend_support_colorburn"; 229 separator = ", "; 230 } 231 if (fFlags & kBlendSupportHardLight_Flag) { 232 result += separator + "blend_support_hardlight"; 233 separator = ", "; 234 } 235 if (fFlags & kBlendSupportSoftLight_Flag) { 236 result += separator + "blend_support_softlight"; 237 separator = ", "; 238 } 239 if (fFlags & kBlendSupportDifference_Flag) { 240 result += separator + "blend_support_difference"; 241 separator = ", "; 242 } 243 if (fFlags & kBlendSupportExclusion_Flag) { 244 result += separator + "blend_support_exclusion"; 245 separator = ", "; 246 } 247 if (fFlags & kBlendSupportHSLHue_Flag) { 248 result += separator + "blend_support_hsl_hue"; 249 separator = ", "; 250 } 251 if (fFlags & kBlendSupportHSLSaturation_Flag) { 252 result += separator + "blend_support_hsl_saturation"; 253 separator = ", "; 254 } 255 if (fFlags & kBlendSupportHSLColor_Flag) { 256 result += separator + "blend_support_hsl_color"; 257 separator = ", "; 258 } 259 if (fFlags & kBlendSupportHSLLuminosity_Flag) { 260 result += separator + "blend_support_hsl_luminosity"; 261 separator = ", "; 262 } 263 if (fFlags & kPushConstant_Flag) { 264 result += separator + "push_constant"; 265 separator = ", "; 266 } 267 switch (fPrimitive) { 268 case kPoints_Primitive: 269 result += separator + "points"; 270 separator = ", "; 271 break; 272 case kLines_Primitive: 273 result += separator + "lines"; 274 separator = ", "; 275 break; 276 case kLineStrip_Primitive: 277 result += separator + "line_strip"; 278 separator = ", "; 279 break; 280 case kLinesAdjacency_Primitive: 281 result += separator + "lines_adjacency"; 282 separator = ", "; 283 break; 284 case kTriangles_Primitive: 285 result += separator + "triangles"; 286 separator = ", "; 287 break; 288 case kTriangleStrip_Primitive: 289 result += separator + "triangle_strip"; 290 separator = ", "; 291 break; 292 case kTrianglesAdjacency_Primitive: 293 result += separator + "triangles_adjacency"; 294 separator = ", "; 295 break; 296 case kUnspecified_Primitive: 297 break; 298 } 299 if (fMaxVertices >= 0) { 300 result += separator + "max_vertices = " + to_string(fMaxVertices); 301 separator = ", "; 302 } 303 if (fInvocations >= 0) { 304 result += separator + "invocations = " + to_string(fInvocations); 305 separator = ", "; 306 } 307 if (fWhen.size()) { 308 result += separator + "when = " + fWhen; 309 separator = ", "; 310 } 311 if (result.size() > 0) { 312 result = "layout (" + result + ")"; 313 } 314 return result; 315 } 316 317 bool operator==(const Layout& other) const { 318 return fFlags == other.fFlags && 319 fLocation == other.fLocation && 320 fOffset == other.fOffset && 321 fBinding == other.fBinding && 322 fIndex == other.fIndex && 323 fSet == other.fSet && 324 fBuiltin == other.fBuiltin && 325 fInputAttachmentIndex == other.fInputAttachmentIndex && 326 fFormat == other.fFormat && 327 fPrimitive == other.fPrimitive && 328 fMaxVertices == other.fMaxVertices && 329 fInvocations == other.fInvocations; 330 } 331 332 bool operator!=(const Layout& other) const { 333 return !(*this == other); 334 } 335 336 int fFlags; 337 int fLocation; 338 int fOffset; 339 int fBinding; 340 int fIndex; 341 int fSet; 342 // builtin comes from SPIR-V and identifies which particular builtin value this object 343 // represents. 344 int fBuiltin; 345 // input_attachment_index comes from Vulkan/SPIR-V to connect a shader variable to the a 346 // corresponding attachment on the subpass in which the shader is being used. 347 int fInputAttachmentIndex; 348 Format fFormat; 349 Primitive fPrimitive; 350 int fMaxVertices; 351 int fInvocations; 352 String fWhen; 353 Key fKey; 354 StringFragment fCType; 355}; 356 357} // namespace 358 359#endif 360