@@ -2176,17 +2176,19 @@ bool AllowsLayout(ValidationState_t& vstate, const spv::StorageClass sc) {
2176
2176
}
2177
2177
}
2178
2178
2179
- bool UsesExplicitLayout (ValidationState_t& vstate, uint32_t type_id,
2180
- std::unordered_map<uint32_t , bool >& cache) {
2179
+ // Returns a decoration used to make it explicit
2180
+ spv::Decoration UsesExplicitLayout (
2181
+ ValidationState_t& vstate, uint32_t type_id,
2182
+ std::unordered_map<uint32_t , spv::Decoration>& cache) {
2181
2183
if (type_id == 0 ) {
2182
- return false ;
2184
+ return spv::Decoration::Max ;
2183
2185
}
2184
2186
2185
2187
if (cache.count (type_id)) {
2186
2188
return cache[type_id];
2187
2189
}
2188
2190
2189
- bool res = false ;
2191
+ spv::Decoration res = spv::Decoration::Max ;
2190
2192
const auto type_inst = vstate.FindDef (type_id);
2191
2193
if (type_inst->opcode () == spv::Op::OpTypeStruct ||
2192
2194
type_inst->opcode () == spv::Op::OpTypeArray ||
@@ -2202,21 +2204,26 @@ bool UsesExplicitLayout(ValidationState_t& vstate, uint32_t type_id,
2202
2204
allowLayoutDecorations = AllowsLayout (vstate, sc);
2203
2205
}
2204
2206
if (!allowLayoutDecorations) {
2205
- res = std::any_of (
2206
- iter->second .begin (), iter->second .end (), [](const Decoration& d) {
2207
- return d.dec_type () == spv::Decoration::Block ||
2208
- d.dec_type () == spv::Decoration::BufferBlock ||
2209
- d.dec_type () == spv::Decoration::Offset ||
2210
- d.dec_type () == spv::Decoration::ArrayStride ||
2211
- d.dec_type () == spv::Decoration::MatrixStride;
2212
- });
2207
+ for (const auto & d : iter->second ) {
2208
+ const spv::Decoration dec = d.dec_type ();
2209
+ if (dec == spv::Decoration::Block ||
2210
+ dec == spv::Decoration::BufferBlock ||
2211
+ dec == spv::Decoration::Offset ||
2212
+ dec == spv::Decoration::ArrayStride ||
2213
+ dec == spv::Decoration::MatrixStride) {
2214
+ res = dec;
2215
+ break ;
2216
+ }
2217
+ }
2213
2218
}
2214
2219
}
2215
2220
2216
- if (! res) {
2221
+ if (res == spv::Decoration::Max ) {
2217
2222
switch (type_inst->opcode ()) {
2218
2223
case spv::Op::OpTypeStruct:
2219
- for (uint32_t i = 1 ; !res && i < type_inst->operands ().size (); i++) {
2224
+ for (uint32_t i = 1 ;
2225
+ res == spv::Decoration::Max && i < type_inst->operands ().size ();
2226
+ i++) {
2220
2227
res = UsesExplicitLayout (
2221
2228
vstate, type_inst->GetOperandAs <uint32_t >(i), cache);
2222
2229
}
@@ -2248,10 +2255,13 @@ spv_result_t CheckInvalidVulkanExplicitLayout(ValidationState_t& vstate) {
2248
2255
return SPV_SUCCESS;
2249
2256
}
2250
2257
2251
- std::unordered_map<uint32_t , bool > cache;
2258
+ std::unordered_map<uint32_t , spv::Decoration > cache;
2252
2259
for (const auto & inst : vstate.ordered_instructions ()) {
2253
2260
const auto type_id = inst.type_id ();
2254
2261
const auto type_inst = vstate.FindDef (type_id);
2262
+
2263
+ spv::StorageClass sc = spv::StorageClass::Max;
2264
+ spv::Decoration layout_dec = spv::Decoration::Max;
2255
2265
uint32_t fail_id = 0 ;
2256
2266
// Variables are the main place to check for improper decorations, but some
2257
2267
// untyped pointer instructions must also be checked since those types may
@@ -2261,16 +2271,18 @@ spv_result_t CheckInvalidVulkanExplicitLayout(ValidationState_t& vstate) {
2261
2271
switch (inst.opcode ()) {
2262
2272
case spv::Op::OpVariable:
2263
2273
case spv::Op::OpUntypedVariableKHR: {
2264
- const auto sc = inst.GetOperandAs <spv::StorageClass>(2 );
2274
+ sc = inst.GetOperandAs <spv::StorageClass>(2 );
2265
2275
auto check_id = type_id;
2266
2276
if (inst.opcode () == spv::Op::OpUntypedVariableKHR) {
2267
2277
if (inst.operands ().size () > 3 ) {
2268
2278
check_id = inst.GetOperandAs <uint32_t >(3 );
2269
2279
}
2270
2280
}
2271
- if (!AllowsLayout (vstate, sc) &&
2272
- UsesExplicitLayout (vstate, check_id, cache)) {
2273
- fail_id = check_id;
2281
+ if (!AllowsLayout (vstate, sc)) {
2282
+ layout_dec = UsesExplicitLayout (vstate, check_id, cache);
2283
+ if (layout_dec != spv::Decoration::Max) {
2284
+ fail_id = check_id;
2285
+ }
2274
2286
}
2275
2287
break ;
2276
2288
}
@@ -2280,13 +2292,17 @@ spv_result_t CheckInvalidVulkanExplicitLayout(ValidationState_t& vstate) {
2280
2292
case spv::Op::OpUntypedInBoundsPtrAccessChainKHR: {
2281
2293
// Check both the base type and return type. The return type may have an
2282
2294
// invalid array stride.
2283
- const auto sc = type_inst->GetOperandAs <spv::StorageClass>(1 );
2284
- const auto base_type_id = inst.GetOperandAs <uint32_t >(2 );
2295
+ sc = type_inst->GetOperandAs <spv::StorageClass>(1 );
2285
2296
if (!AllowsLayout (vstate, sc)) {
2286
- if (UsesExplicitLayout (vstate, base_type_id, cache)) {
2297
+ const auto base_type_id = inst.GetOperandAs <uint32_t >(2 );
2298
+ layout_dec = UsesExplicitLayout (vstate, base_type_id, cache);
2299
+ if (layout_dec != spv::Decoration::Max) {
2287
2300
fail_id = base_type_id;
2288
- } else if (UsesExplicitLayout (vstate, type_id, cache)) {
2289
- fail_id = type_id;
2301
+ } else {
2302
+ layout_dec = UsesExplicitLayout (vstate, type_id, cache);
2303
+ if (layout_dec != spv::Decoration::Max) {
2304
+ fail_id = type_id;
2305
+ }
2290
2306
}
2291
2307
}
2292
2308
break ;
@@ -2296,11 +2312,13 @@ spv_result_t CheckInvalidVulkanExplicitLayout(ValidationState_t& vstate) {
2296
2312
const auto ptr_ty_id =
2297
2313
vstate.FindDef (inst.GetOperandAs <uint32_t >(3 ))->type_id ();
2298
2314
const auto ptr_ty = vstate.FindDef (ptr_ty_id);
2299
- const auto sc = ptr_ty->GetOperandAs <spv::StorageClass>(1 );
2300
- const auto base_type_id = inst.GetOperandAs <uint32_t >(2 );
2301
- if (!AllowsLayout (vstate, sc) &&
2302
- UsesExplicitLayout (vstate, base_type_id, cache)) {
2303
- fail_id = base_type_id;
2315
+ sc = ptr_ty->GetOperandAs <spv::StorageClass>(1 );
2316
+ if (!AllowsLayout (vstate, sc)) {
2317
+ const auto base_type_id = inst.GetOperandAs <uint32_t >(2 );
2318
+ layout_dec = UsesExplicitLayout (vstate, base_type_id, cache);
2319
+ if (layout_dec != spv::Decoration::Max) {
2320
+ fail_id = base_type_id;
2321
+ }
2304
2322
}
2305
2323
break ;
2306
2324
}
@@ -2309,10 +2327,12 @@ spv_result_t CheckInvalidVulkanExplicitLayout(ValidationState_t& vstate) {
2309
2327
const auto ptr_type = vstate.FindDef (vstate.FindDef (ptr_id)->type_id ());
2310
2328
if (ptr_type->opcode () == spv::Op::OpTypeUntypedPointerKHR) {
2311
2329
// For untyped pointers check the return type for an invalid layout.
2312
- const auto sc = ptr_type->GetOperandAs <spv::StorageClass>(1 );
2313
- if (!AllowsLayout (vstate, sc) &&
2314
- UsesExplicitLayout (vstate, type_id, cache)) {
2315
- fail_id = type_id;
2330
+ sc = ptr_type->GetOperandAs <spv::StorageClass>(1 );
2331
+ if (!AllowsLayout (vstate, sc)) {
2332
+ layout_dec = UsesExplicitLayout (vstate, type_id, cache);
2333
+ if (layout_dec != spv::Decoration::Max) {
2334
+ fail_id = type_id;
2335
+ }
2316
2336
}
2317
2337
}
2318
2338
break ;
@@ -2323,11 +2343,13 @@ spv_result_t CheckInvalidVulkanExplicitLayout(ValidationState_t& vstate) {
2323
2343
if (ptr_type->opcode () == spv::Op::OpTypeUntypedPointerKHR) {
2324
2344
// For untyped pointers, check the type of the data operand for an
2325
2345
// invalid layout.
2326
- const auto sc = ptr_type->GetOperandAs <spv::StorageClass>(1 );
2327
- const auto data_type_id = vstate.GetOperandTypeId (&inst, 1 );
2328
- if (!AllowsLayout (vstate, sc) &&
2329
- UsesExplicitLayout (vstate, data_type_id, cache)) {
2330
- fail_id = inst.GetOperandAs <uint32_t >(2 );
2346
+ sc = ptr_type->GetOperandAs <spv::StorageClass>(1 );
2347
+ if (!AllowsLayout (vstate, sc)) {
2348
+ const auto data_type_id = vstate.GetOperandTypeId (&inst, 1 );
2349
+ layout_dec = UsesExplicitLayout (vstate, data_type_id, cache);
2350
+ if (layout_dec != spv::Decoration::Max) {
2351
+ fail_id = inst.GetOperandAs <uint32_t >(2 );
2352
+ }
2331
2353
}
2332
2354
}
2333
2355
break ;
@@ -2339,7 +2361,10 @@ spv_result_t CheckInvalidVulkanExplicitLayout(ValidationState_t& vstate) {
2339
2361
return vstate.diag (SPV_ERROR_INVALID_ID, &inst)
2340
2362
<< vstate.VkErrorID (10684 )
2341
2363
<< " Invalid explicit layout decorations on type for operand "
2342
- << vstate.getIdName (fail_id);
2364
+ << vstate.getIdName (fail_id) << " , the "
2365
+ << spvtools::StorageClassToString (sc)
2366
+ << " storage class has a explicit layout from the "
2367
+ << vstate.SpvDecorationString (layout_dec) << " decoration." ;
2343
2368
}
2344
2369
}
2345
2370
0 commit comments