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 "SkString.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 static const char* FormatToStr(Format format) { 47 switch (format) { 48 case Format::kUnspecified: return ""; 49 case Format::kRGBA32F: return "rgba32f"; 50 case Format::kR32F: return "r32f"; 51 case Format::kRGBA16F: return "rgba16f"; 52 case Format::kR16F: return "r16f"; 53 case Format::kRGBA8: return "rgba8"; 54 case Format::kR8: return "r8"; 55 case Format::kRGBA8I: return "rgba8i"; 56 case Format::kR8I: return "r8i"; 57 } 58 SkFAIL("Unexpected format"); 59 return ""; 60 } 61 62 static bool ReadFormat(SkString str, Format* format) { 63 if (str == "rgba32f") { 64 *format = Format::kRGBA32F; 65 return true; 66 } else if (str == "r32f") { 67 *format = Format::kR32F; 68 return true; 69 } else if (str == "rgba16f") { 70 *format = Format::kRGBA16F; 71 return true; 72 } else if (str == "r16f") { 73 *format = Format::kR16F; 74 return true; 75 } else if (str == "rgba8") { 76 *format = Format::kRGBA8; 77 return true; 78 } else if (str == "r8") { 79 *format = Format::kR8; 80 return true; 81 } else if (str == "rgba8i") { 82 *format = Format::kRGBA8I; 83 return true; 84 } else if (str == "r8i") { 85 *format = Format::kR8I; 86 return true; 87 } 88 return false; 89 } 90 91 Layout(int location, int offset, int binding, int index, int set, int builtin, 92 int inputAttachmentIndex, bool originUpperLeft, bool overrideCoverage, 93 bool blendSupportAllEquations, Format format, bool pushconstant, Primitive primitive, 94 int maxVertices, int invocations) 95 : fLocation(location) 96 , fOffset(offset) 97 , fBinding(binding) 98 , fIndex(index) 99 , fSet(set) 100 , fBuiltin(builtin) 101 , fInputAttachmentIndex(inputAttachmentIndex) 102 , fOriginUpperLeft(originUpperLeft) 103 , fOverrideCoverage(overrideCoverage) 104 , fBlendSupportAllEquations(blendSupportAllEquations) 105 , fFormat(format) 106 , fPushConstant(pushconstant) 107 , fPrimitive(primitive) 108 , fMaxVertices(maxVertices) 109 , fInvocations(invocations) {} 110 111 Layout() 112 : fLocation(-1) 113 , fOffset(-1) 114 , fBinding(-1) 115 , fIndex(-1) 116 , fSet(-1) 117 , fBuiltin(-1) 118 , fInputAttachmentIndex(-1) 119 , fOriginUpperLeft(false) 120 , fOverrideCoverage(false) 121 , fBlendSupportAllEquations(false) 122 , fFormat(Format::kUnspecified) 123 , fPushConstant(false) 124 , fPrimitive(kUnspecified_Primitive) 125 , fMaxVertices(-1) 126 , fInvocations(-1) {} 127 128 SkString description() const { 129 SkString result; 130 SkString separator; 131 if (fLocation >= 0) { 132 result += separator + "location = " + to_string(fLocation); 133 separator = ", "; 134 } 135 if (fOffset >= 0) { 136 result += separator + "offset = " + to_string(fOffset); 137 separator = ", "; 138 } 139 if (fBinding >= 0) { 140 result += separator + "binding = " + to_string(fBinding); 141 separator = ", "; 142 } 143 if (fIndex >= 0) { 144 result += separator + "index = " + to_string(fIndex); 145 separator = ", "; 146 } 147 if (fSet >= 0) { 148 result += separator + "set = " + to_string(fSet); 149 separator = ", "; 150 } 151 if (fBuiltin >= 0) { 152 result += separator + "builtin = " + to_string(fBuiltin); 153 separator = ", "; 154 } 155 if (fInputAttachmentIndex >= 0) { 156 result += separator + "input_attachment_index = " + to_string(fBuiltin); 157 separator = ", "; 158 } 159 if (fOriginUpperLeft) { 160 result += separator + "origin_upper_left"; 161 separator = ", "; 162 } 163 if (fOverrideCoverage) { 164 result += separator + "override_coverage"; 165 separator = ", "; 166 } 167 if (fBlendSupportAllEquations) { 168 result += separator + "blend_support_all_equations"; 169 separator = ", "; 170 } 171 if (Format::kUnspecified != fFormat) { 172 result += separator + FormatToStr(fFormat); 173 separator = ", "; 174 } 175 if (fPushConstant) { 176 result += separator + "push_constant"; 177 separator = ", "; 178 } 179 switch (fPrimitive) { 180 case kPoints_Primitive: 181 result += separator + "points"; 182 separator = ", "; 183 break; 184 case kLines_Primitive: 185 result += separator + "lines"; 186 separator = ", "; 187 break; 188 case kLineStrip_Primitive: 189 result += separator + "line_strip"; 190 separator = ", "; 191 break; 192 case kLinesAdjacency_Primitive: 193 result += separator + "lines_adjacency"; 194 separator = ", "; 195 break; 196 case kTriangles_Primitive: 197 result += separator + "triangles"; 198 separator = ", "; 199 break; 200 case kTriangleStrip_Primitive: 201 result += separator + "triangle_strip"; 202 separator = ", "; 203 break; 204 case kTrianglesAdjacency_Primitive: 205 result += separator + "triangles_adjacency"; 206 separator = ", "; 207 break; 208 case kUnspecified_Primitive: 209 break; 210 } 211 if (fMaxVertices >= 0) { 212 result += separator + "max_vertices = " + to_string(fMaxVertices); 213 separator = ", "; 214 } 215 if (fInvocations >= 0) { 216 result += separator + "invocations = " + to_string(fInvocations); 217 separator = ", "; 218 } 219 if (result.size() > 0) { 220 result = "layout (" + result + ")"; 221 } 222 return result; 223 } 224 225 bool operator==(const Layout& other) const { 226 return fLocation == other.fLocation && 227 fOffset == other.fOffset && 228 fBinding == other.fBinding && 229 fIndex == other.fIndex && 230 fSet == other.fSet && 231 fBuiltin == other.fBuiltin && 232 fInputAttachmentIndex == other.fInputAttachmentIndex && 233 fOriginUpperLeft == other.fOriginUpperLeft && 234 fOverrideCoverage == other.fOverrideCoverage && 235 fBlendSupportAllEquations == other.fBlendSupportAllEquations && 236 fFormat == other.fFormat && 237 fPrimitive == other.fPrimitive && 238 fMaxVertices == other.fMaxVertices && 239 fInvocations == other.fInvocations; 240 } 241 242 bool operator!=(const Layout& other) const { 243 return !(*this == other); 244 } 245 246 int fLocation; 247 int fOffset; 248 int fBinding; 249 int fIndex; 250 int fSet; 251 // builtin comes from SPIR-V and identifies which particular builtin value this object 252 // represents. 253 int fBuiltin; 254 // input_attachment_index comes from Vulkan/SPIR-V to connect a shader variable to the a 255 // corresponding attachment on the subpass in which the shader is being used. 256 int fInputAttachmentIndex; 257 bool fOriginUpperLeft; 258 bool fOverrideCoverage; 259 bool fBlendSupportAllEquations; 260 Format fFormat; 261 bool fPushConstant; 262 Primitive fPrimitive; 263 int fMaxVertices; 264 int fInvocations; 265 }; 266 267 } // namespace 268 269 #endif 270