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