103 {
106
110 "' must be global");
111 }
113 context.fErrors->error(
pos,
"'in' variables may not have matrix type");
114 }
116 context.fErrors->error(
pos,
"'in' variables may not have unsized array type");
117 }
119 context.fErrors->error(
pos,
"'out' variables may not have unsized array type");
120 }
122 context.fErrors->error(
pos,
"'in uniform' variables not permitted");
123 }
124 if (modifierFlags.isReadOnly() && modifierFlags.isWriteOnly()) {
125 context.fErrors->error(
pos,
"'readonly' and 'writeonly' qualifiers cannot be combined");
126 }
127 if (modifierFlags.isUniform() && modifierFlags.isBuffer()) {
128 context.fErrors->error(
pos,
"'uniform buffer' variables not permitted");
129 }
132 context.fErrors->error(
pos,
"in / out variables may not be declared workgroup");
133 }
134 if (modifierFlags.isUniform()) {
136 }
139 "' must be uniform");
140 }
142 context.fErrors->error(
pos,
"effects are not permitted in mesh vertex shaders");
143 }
145
146
147
148
149
150
151
152
153
154
155 bool isBlockMember = (storage == Variable::Storage::kInterfaceBlock);
156 bool isWritableStorageBuffer = modifierFlags.isBuffer() && !modifierFlags.isReadOnly();
157
158 if (!modifierFlags.isWorkgroup() &&
160 context.fErrors->error(
pos,
"atomics are only permitted in workgroup variables and "
161 "writable storage blocks");
162 }
163 }
166 context.fErrors->error(
pos,
"'layout(color)' is only permitted in runtime effects");
167 }
168 if (!modifierFlags.isUniform()) {
169 context.fErrors->error(
pos,
"'layout(color)' is only permitted on 'uniform' variables");
170 }
171 auto validColorXformType = [](
const Type& t) {
172 return t.isVector() && t.componentType().isFloat() &&
173 (t.columns() == 3 || t.columns() == 4);
174 };
175 if (!validColorXformType(*
baseType)) {
176 context.fErrors->error(
pos,
"'layout(color)' is not permitted on variables of type '" +
178 }
179 }
180
184
186
187
190
192
193 if (modifierFlags.isBuffer()) {
194
195
196
198 }
199
200
201
203 const int illegalRangeEnd =
SkToInt(fields.size()) -
204 (modifierFlags.isBuffer() ? 1 : 0);
205 for (
int i = 0;
i < illegalRangeEnd; ++
i) {
206 if (fields[
i].fType->isUnsizedArray()) {
207 context.fErrors->error(
209 "unsized array must be the last member of a storage block");
210 }
211 }
212 }
213
215
217 }
220
222 }
224
227 }
228 } else {
229
231 }
232 }
233 }
234
236
237
240 context.fErrors->error(
pos,
"storage textures must declare a pixel format");
241 }
242 } else {
243 permittedLayoutFlags &= ~LayoutFlag::kAllPixelFormats;
244 }
245
246
247
250
251 break;
253 permittedLayoutFlags &= ~LayoutFlag::kSampler;
254 break;
256 permittedLayoutFlags &= ~LayoutFlag::kTexture;
257 break;
258 default:
260 break;
261 }
262
263
264
265
271 !permitBindingAndSet)) {
272 permittedLayoutFlags &= ~LayoutFlag::kBinding;
273 permittedLayoutFlags &= ~LayoutFlag::kSet;
274 permittedLayoutFlags &= ~LayoutFlag::kAllBackends;
275 }
277
279 }
280
281
284 permittedLayoutFlags &= ~LayoutFlag::kPushConstant;
285 }
286
287 if (!context.fConfig->fIsBuiltinCode) {
288 permittedLayoutFlags &= ~LayoutFlag::kBuiltin;
289 }
290
291 modifierFlags.checkPermittedFlags(context, modifiersPosition, permitted);
292 layout.checkPermittedLayout(context, modifiersPosition, permittedLayoutFlags);
293}
constexpr int SkToInt(S x)
bool isEffectChild() const
virtual bool isInterfaceBlock() const
virtual SkSpan< const Field > fields() const
virtual bool isMatrix() const
virtual bool isOrContainsAtomic() const
bool isStorageTexture() const
std::string displayName() const
TypeKind typeKind() const
virtual bool isStruct() const
SkEnumBitMask< SkSL::LayoutFlag > LayoutFlags
static bool IsRuntimeEffect(ProgramKind kind)
static bool IsFragment(ProgramKind kind)
static bool IsCompute(ProgramKind kind)