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 "include/private/SkSLString.h" 12 13 namespace SkSL { 14 15 /** 16 * Represents a layout block appearing before a variable declaration, as in: 17 * 18 * layout (location = 0) int x; 19 */ 20 struct Layout { 21 enum Flag { 22 kOriginUpperLeft_Flag = 1 << 0, 23 kOverrideCoverage_Flag = 1 << 1, 24 kPushConstant_Flag = 1 << 2, 25 kBlendSupportAllEquations_Flag = 1 << 3, 26 kTracked_Flag = 1 << 4, 27 kSRGBUnpremul_Flag = 1 << 5, 28 kKey_Flag = 1 << 6, 29 30 // These flags indicate if the qualifier appeared, regardless of the accompanying value. 31 kLocation_Flag = 1 << 7, 32 kOffset_Flag = 1 << 8, 33 kBinding_Flag = 1 << 9, 34 kIndex_Flag = 1 << 10, 35 kSet_Flag = 1 << 11, 36 kBuiltin_Flag = 1 << 12, 37 kInputAttachmentIndex_Flag = 1 << 13, 38 kPrimitive_Flag = 1 << 14, 39 kMaxVertices_Flag = 1 << 15, 40 kInvocations_Flag = 1 << 16, 41 kWhen_Flag = 1 << 17, 42 kCType_Flag = 1 << 18, 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 enum class CType { 57 kDefault, 58 kBool, 59 kFloat, 60 kFloat2, 61 kFloat3, 62 kFloat4, 63 kInt32, 64 kSkRect, 65 kSkIRect, 66 kSkPMColor4f, 67 kSkPMColor, 68 kSkV4, 69 kSkPoint, 70 kSkIPoint, 71 kSkMatrix, 72 kSkM44, 73 kGrSurfaceProxyView, 74 kGrFragmentProcessor, 75 }; 76 CTypeToStrLayout77 static const char* CTypeToStr(CType ctype) { 78 switch (ctype) { 79 case CType::kDefault: 80 return nullptr; 81 case CType::kFloat: 82 return "float"; 83 case CType::kInt32: 84 return "int32_t"; 85 case CType::kSkRect: 86 return "SkRect"; 87 case CType::kSkIRect: 88 return "SkIRect"; 89 case CType::kSkPMColor4f: 90 return "SkPMColor4f"; 91 case CType::kSkPMColor: 92 return "SkPMColor"; 93 case CType::kSkV4: 94 return "SkV4"; 95 case CType::kSkPoint: 96 return "SkPoint"; 97 case CType::kSkIPoint: 98 return "SkIPoint"; 99 case CType::kSkMatrix: 100 return "SkMatrix"; 101 case CType::kSkM44: 102 return "SkM44"; 103 case CType::kGrSurfaceProxyView: 104 return "GrSurfaceProxyView"; 105 case CType::kGrFragmentProcessor: 106 return "std::unique_ptr<GrFragmentProcessor>"; 107 default: 108 SkASSERT(false); 109 return nullptr; 110 } 111 } 112 LayoutLayout113 Layout(int flags, int location, int offset, int binding, int index, int set, int builtin, 114 int inputAttachmentIndex, Primitive primitive, int maxVertices, int invocations, 115 StringFragment when, CType ctype) 116 : fFlags(flags) 117 , fLocation(location) 118 , fOffset(offset) 119 , fBinding(binding) 120 , fIndex(index) 121 , fSet(set) 122 , fBuiltin(builtin) 123 , fInputAttachmentIndex(inputAttachmentIndex) 124 , fPrimitive(primitive) 125 , fMaxVertices(maxVertices) 126 , fInvocations(invocations) 127 , fWhen(when) 128 , fCType(ctype) {} 129 LayoutLayout130 Layout() 131 : fFlags(0) 132 , fLocation(-1) 133 , fOffset(-1) 134 , fBinding(-1) 135 , fIndex(-1) 136 , fSet(-1) 137 , fBuiltin(-1) 138 , fInputAttachmentIndex(-1) 139 , fPrimitive(kUnspecified_Primitive) 140 , fMaxVertices(-1) 141 , fInvocations(-1) 142 , fCType(CType::kDefault) {} 143 builtinLayout144 static Layout builtin(int builtin) { 145 Layout result; 146 result.fBuiltin = builtin; 147 return result; 148 } 149 descriptionLayout150 String description() const { 151 String result; 152 auto separator = [firstSeparator = true]() mutable -> String { 153 if (firstSeparator) { 154 firstSeparator = false; 155 return ""; 156 } else { 157 return ", "; 158 }}; 159 if (fLocation >= 0) { 160 result += separator() + "location = " + to_string(fLocation); 161 } 162 if (fOffset >= 0) { 163 result += separator() + "offset = " + to_string(fOffset); 164 } 165 if (fBinding >= 0) { 166 result += separator() + "binding = " + to_string(fBinding); 167 } 168 if (fIndex >= 0) { 169 result += separator() + "index = " + to_string(fIndex); 170 } 171 if (fSet >= 0) { 172 result += separator() + "set = " + to_string(fSet); 173 } 174 if (fBuiltin >= 0) { 175 result += separator() + "builtin = " + to_string(fBuiltin); 176 } 177 if (fInputAttachmentIndex >= 0) { 178 result += separator() + "input_attachment_index = " + to_string(fInputAttachmentIndex); 179 } 180 if (fFlags & kOriginUpperLeft_Flag) { 181 result += separator() + "origin_upper_left"; 182 } 183 if (fFlags & kOverrideCoverage_Flag) { 184 result += separator() + "override_coverage"; 185 } 186 if (fFlags & kBlendSupportAllEquations_Flag) { 187 result += separator() + "blend_support_all_equations"; 188 } 189 if (fFlags & kPushConstant_Flag) { 190 result += separator() + "push_constant"; 191 } 192 if (fFlags & kTracked_Flag) { 193 result += separator() + "tracked"; 194 } 195 if (fFlags & kSRGBUnpremul_Flag) { 196 result += separator() + "srgb_unpremul"; 197 } 198 switch (fPrimitive) { 199 case kPoints_Primitive: 200 result += separator() + "points"; 201 break; 202 case kLines_Primitive: 203 result += separator() + "lines"; 204 break; 205 case kLineStrip_Primitive: 206 result += separator() + "line_strip"; 207 break; 208 case kLinesAdjacency_Primitive: 209 result += separator() + "lines_adjacency"; 210 break; 211 case kTriangles_Primitive: 212 result += separator() + "triangles"; 213 break; 214 case kTriangleStrip_Primitive: 215 result += separator() + "triangle_strip"; 216 break; 217 case kTrianglesAdjacency_Primitive: 218 result += separator() + "triangles_adjacency"; 219 break; 220 case kUnspecified_Primitive: 221 break; 222 } 223 if (fMaxVertices >= 0) { 224 result += separator() + "max_vertices = " + to_string(fMaxVertices); 225 } 226 if (fInvocations >= 0) { 227 result += separator() + "invocations = " + to_string(fInvocations); 228 } 229 if (fWhen.fLength) { 230 result += separator() + "when = " + fWhen; 231 } 232 if (result.size() > 0) { 233 result = "layout (" + result + ")"; 234 } 235 if (fFlags & kKey_Flag) { 236 result += "/* key */ const"; 237 } 238 return result; 239 } 240 241 bool operator==(const Layout& other) const { 242 return fFlags == other.fFlags && 243 fLocation == other.fLocation && 244 fOffset == other.fOffset && 245 fBinding == other.fBinding && 246 fIndex == other.fIndex && 247 fSet == other.fSet && 248 fBuiltin == other.fBuiltin && 249 fInputAttachmentIndex == other.fInputAttachmentIndex && 250 fPrimitive == other.fPrimitive && 251 fMaxVertices == other.fMaxVertices && 252 fInvocations == other.fInvocations && 253 fWhen == other.fWhen && 254 fCType == other.fCType; 255 } 256 257 bool operator!=(const Layout& other) const { 258 return !(*this == other); 259 } 260 261 int fFlags; 262 int fLocation; 263 int fOffset; 264 int fBinding; 265 int fIndex; 266 int fSet; 267 // builtin comes from SPIR-V and identifies which particular builtin value this object 268 // represents. 269 int fBuiltin; 270 // input_attachment_index comes from Vulkan/SPIR-V to connect a shader variable to the a 271 // corresponding attachment on the subpass in which the shader is being used. 272 int fInputAttachmentIndex; 273 Primitive fPrimitive; 274 int fMaxVertices; 275 int fInvocations; 276 StringFragment fWhen; 277 CType fCType; 278 }; 279 280 } // namespace SkSL 281 282 #endif 283