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 Primitive { 23 kUnspecified_Primitive = -1, 24 kPoints_Primitive, 25 kLines_Primitive, 26 kLineStrip_Primitive, 27 kLinesAdjacency_Primitive, 28 kTriangles_Primitive, 29 kTriangleStrip_Primitive, 30 kTrianglesAdjacency_Primitive 31 }; 32 33 // These are used by images in GLSL. We only support a subset of what GL supports. 34 enum class Format { 35 kUnspecified = -1, 36 kRGBA32F, 37 kR32F, 38 kRGBA16F, 39 kR16F, 40 kRGBA8, 41 kR8, 42 kRGBA8I, 43 kR8I, 44 }; 45 46 // used by SkSL processors 47 enum Key { 48 // field is not a key 49 kNo_Key, 50 // field is a key 51 kKey_Key, 52 // key is 0 or 1 depending on whether the matrix is an identity matrix 53 kIdentity_Key, 54 }; 55 FormatToStrLayout56 static const char* FormatToStr(Format format) { 57 switch (format) { 58 case Format::kUnspecified: return ""; 59 case Format::kRGBA32F: return "rgba32f"; 60 case Format::kR32F: return "r32f"; 61 case Format::kRGBA16F: return "rgba16f"; 62 case Format::kR16F: return "r16f"; 63 case Format::kRGBA8: return "rgba8"; 64 case Format::kR8: return "r8"; 65 case Format::kRGBA8I: return "rgba8i"; 66 case Format::kR8I: return "r8i"; 67 } 68 ABORT("Unexpected format"); 69 } 70 ReadFormatLayout71 static bool ReadFormat(String str, Format* format) { 72 if (str == "rgba32f") { 73 *format = Format::kRGBA32F; 74 return true; 75 } else if (str == "r32f") { 76 *format = Format::kR32F; 77 return true; 78 } else if (str == "rgba16f") { 79 *format = Format::kRGBA16F; 80 return true; 81 } else if (str == "r16f") { 82 *format = Format::kR16F; 83 return true; 84 } else if (str == "rgba8") { 85 *format = Format::kRGBA8; 86 return true; 87 } else if (str == "r8") { 88 *format = Format::kR8; 89 return true; 90 } else if (str == "rgba8i") { 91 *format = Format::kRGBA8I; 92 return true; 93 } else if (str == "r8i") { 94 *format = Format::kR8I; 95 return true; 96 } 97 return false; 98 } 99 LayoutLayout100 Layout(int location, int offset, int binding, int index, int set, int builtin, 101 int inputAttachmentIndex, bool originUpperLeft, bool overrideCoverage, 102 bool blendSupportAllEquations, Format format, bool pushconstant, Primitive primitive, 103 int maxVertices, int invocations, String when, Key key) 104 : fLocation(location) 105 , fOffset(offset) 106 , fBinding(binding) 107 , fIndex(index) 108 , fSet(set) 109 , fBuiltin(builtin) 110 , fInputAttachmentIndex(inputAttachmentIndex) 111 , fOriginUpperLeft(originUpperLeft) 112 , fOverrideCoverage(overrideCoverage) 113 , fBlendSupportAllEquations(blendSupportAllEquations) 114 , fFormat(format) 115 , fPushConstant(pushconstant) 116 , fPrimitive(primitive) 117 , fMaxVertices(maxVertices) 118 , fInvocations(invocations) 119 , fWhen(when) 120 , fKey(key) {} 121 LayoutLayout122 Layout() 123 : fLocation(-1) 124 , fOffset(-1) 125 , fBinding(-1) 126 , fIndex(-1) 127 , fSet(-1) 128 , fBuiltin(-1) 129 , fInputAttachmentIndex(-1) 130 , fOriginUpperLeft(false) 131 , fOverrideCoverage(false) 132 , fBlendSupportAllEquations(false) 133 , fFormat(Format::kUnspecified) 134 , fPushConstant(false) 135 , fPrimitive(kUnspecified_Primitive) 136 , fMaxVertices(-1) 137 , fInvocations(-1) 138 , fKey(kNo_Key) {} 139 descriptionLayout140 String description() const { 141 String result; 142 String separator; 143 if (fLocation >= 0) { 144 result += separator + "location = " + to_string(fLocation); 145 separator = ", "; 146 } 147 if (fOffset >= 0) { 148 result += separator + "offset = " + to_string(fOffset); 149 separator = ", "; 150 } 151 if (fBinding >= 0) { 152 result += separator + "binding = " + to_string(fBinding); 153 separator = ", "; 154 } 155 if (fIndex >= 0) { 156 result += separator + "index = " + to_string(fIndex); 157 separator = ", "; 158 } 159 if (fSet >= 0) { 160 result += separator + "set = " + to_string(fSet); 161 separator = ", "; 162 } 163 if (fBuiltin >= 0) { 164 result += separator + "builtin = " + to_string(fBuiltin); 165 separator = ", "; 166 } 167 if (fInputAttachmentIndex >= 0) { 168 result += separator + "input_attachment_index = " + to_string(fBuiltin); 169 separator = ", "; 170 } 171 if (fOriginUpperLeft) { 172 result += separator + "origin_upper_left"; 173 separator = ", "; 174 } 175 if (fOverrideCoverage) { 176 result += separator + "override_coverage"; 177 separator = ", "; 178 } 179 if (fBlendSupportAllEquations) { 180 result += separator + "blend_support_all_equations"; 181 separator = ", "; 182 } 183 if (Format::kUnspecified != fFormat) { 184 result += separator + FormatToStr(fFormat); 185 separator = ", "; 186 } 187 if (fPushConstant) { 188 result += separator + "push_constant"; 189 separator = ", "; 190 } 191 switch (fPrimitive) { 192 case kPoints_Primitive: 193 result += separator + "points"; 194 separator = ", "; 195 break; 196 case kLines_Primitive: 197 result += separator + "lines"; 198 separator = ", "; 199 break; 200 case kLineStrip_Primitive: 201 result += separator + "line_strip"; 202 separator = ", "; 203 break; 204 case kLinesAdjacency_Primitive: 205 result += separator + "lines_adjacency"; 206 separator = ", "; 207 break; 208 case kTriangles_Primitive: 209 result += separator + "triangles"; 210 separator = ", "; 211 break; 212 case kTriangleStrip_Primitive: 213 result += separator + "triangle_strip"; 214 separator = ", "; 215 break; 216 case kTrianglesAdjacency_Primitive: 217 result += separator + "triangles_adjacency"; 218 separator = ", "; 219 break; 220 case kUnspecified_Primitive: 221 break; 222 } 223 if (fMaxVertices >= 0) { 224 result += separator + "max_vertices = " + to_string(fMaxVertices); 225 separator = ", "; 226 } 227 if (fInvocations >= 0) { 228 result += separator + "invocations = " + to_string(fInvocations); 229 separator = ", "; 230 } 231 if (fWhen.size()) { 232 result += separator + "when = " + fWhen; 233 separator = ", "; 234 } 235 switch (fKey) { 236 case kNo_Key: 237 break; 238 case kKey_Key: 239 result += separator + "key"; 240 separator = ", "; 241 break; 242 case kIdentity_Key: 243 result += separator + "key=identity"; 244 separator = ", "; 245 break; 246 } 247 if (result.size() > 0) { 248 result = "layout (" + result + ")"; 249 } 250 return result; 251 } 252 253 bool operator==(const Layout& other) const { 254 return fLocation == other.fLocation && 255 fOffset == other.fOffset && 256 fBinding == other.fBinding && 257 fIndex == other.fIndex && 258 fSet == other.fSet && 259 fBuiltin == other.fBuiltin && 260 fInputAttachmentIndex == other.fInputAttachmentIndex && 261 fOriginUpperLeft == other.fOriginUpperLeft && 262 fOverrideCoverage == other.fOverrideCoverage && 263 fBlendSupportAllEquations == other.fBlendSupportAllEquations && 264 fFormat == other.fFormat && 265 fPrimitive == other.fPrimitive && 266 fMaxVertices == other.fMaxVertices && 267 fInvocations == other.fInvocations; 268 } 269 270 bool operator!=(const Layout& other) const { 271 return !(*this == other); 272 } 273 274 int fLocation; 275 int fOffset; 276 int fBinding; 277 int fIndex; 278 int fSet; 279 // builtin comes from SPIR-V and identifies which particular builtin value this object 280 // represents. 281 int fBuiltin; 282 // input_attachment_index comes from Vulkan/SPIR-V to connect a shader variable to the a 283 // corresponding attachment on the subpass in which the shader is being used. 284 int fInputAttachmentIndex; 285 bool fOriginUpperLeft; 286 bool fOverrideCoverage; 287 bool fBlendSupportAllEquations; 288 Format fFormat; 289 bool fPushConstant; 290 Primitive fPrimitive; 291 int fMaxVertices; 292 int fInvocations; 293 String fWhen; 294 Key fKey; 295 }; 296 297 } // namespace 298 299 #endif 300