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