@@ -2176,17 +2176,19 @@ bool AllowsLayout(ValidationState_t& vstate, const spv::StorageClass sc) {
21762176 }
21772177}
21782178
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) {
21812183 if (type_id == 0 ) {
2182- return false ;
2184+ return spv::Decoration::Max ;
21832185 }
21842186
21852187 if (cache.count (type_id)) {
21862188 return cache[type_id];
21872189 }
21882190
2189- bool res = false ;
2191+ spv::Decoration res = spv::Decoration::Max ;
21902192 const auto type_inst = vstate.FindDef (type_id);
21912193 if (type_inst->opcode () == spv::Op::OpTypeStruct ||
21922194 type_inst->opcode () == spv::Op::OpTypeArray ||
@@ -2202,21 +2204,26 @@ bool UsesExplicitLayout(ValidationState_t& vstate, uint32_t type_id,
22022204 allowLayoutDecorations = AllowsLayout (vstate, sc);
22032205 }
22042206 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+ }
22132218 }
22142219 }
22152220
2216- if (! res) {
2221+ if (res == spv::Decoration::Max ) {
22172222 switch (type_inst->opcode ()) {
22182223 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++) {
22202227 res = UsesExplicitLayout (
22212228 vstate, type_inst->GetOperandAs <uint32_t >(i), cache);
22222229 }
@@ -2248,10 +2255,13 @@ spv_result_t CheckInvalidVulkanExplicitLayout(ValidationState_t& vstate) {
22482255 return SPV_SUCCESS;
22492256 }
22502257
2251- std::unordered_map<uint32_t , bool > cache;
2258+ std::unordered_map<uint32_t , spv::Decoration > cache;
22522259 for (const auto & inst : vstate.ordered_instructions ()) {
22532260 const auto type_id = inst.type_id ();
22542261 const auto type_inst = vstate.FindDef (type_id);
2262+
2263+ spv::StorageClass sc = spv::StorageClass::Max;
2264+ spv::Decoration layout_dec = spv::Decoration::Max;
22552265 uint32_t fail_id = 0 ;
22562266 // Variables are the main place to check for improper decorations, but some
22572267 // untyped pointer instructions must also be checked since those types may
@@ -2261,16 +2271,18 @@ spv_result_t CheckInvalidVulkanExplicitLayout(ValidationState_t& vstate) {
22612271 switch (inst.opcode ()) {
22622272 case spv::Op::OpVariable:
22632273 case spv::Op::OpUntypedVariableKHR: {
2264- const auto sc = inst.GetOperandAs <spv::StorageClass>(2 );
2274+ sc = inst.GetOperandAs <spv::StorageClass>(2 );
22652275 auto check_id = type_id;
22662276 if (inst.opcode () == spv::Op::OpUntypedVariableKHR) {
22672277 if (inst.operands ().size () > 3 ) {
22682278 check_id = inst.GetOperandAs <uint32_t >(3 );
22692279 }
22702280 }
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+ }
22742286 }
22752287 break ;
22762288 }
@@ -2280,13 +2292,17 @@ spv_result_t CheckInvalidVulkanExplicitLayout(ValidationState_t& vstate) {
22802292 case spv::Op::OpUntypedInBoundsPtrAccessChainKHR: {
22812293 // Check both the base type and return type. The return type may have an
22822294 // 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 );
22852296 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) {
22872300 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+ }
22902306 }
22912307 }
22922308 break ;
@@ -2296,11 +2312,13 @@ spv_result_t CheckInvalidVulkanExplicitLayout(ValidationState_t& vstate) {
22962312 const auto ptr_ty_id =
22972313 vstate.FindDef (inst.GetOperandAs <uint32_t >(3 ))->type_id ();
22982314 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+ }
23042322 }
23052323 break ;
23062324 }
@@ -2309,10 +2327,12 @@ spv_result_t CheckInvalidVulkanExplicitLayout(ValidationState_t& vstate) {
23092327 const auto ptr_type = vstate.FindDef (vstate.FindDef (ptr_id)->type_id ());
23102328 if (ptr_type->opcode () == spv::Op::OpTypeUntypedPointerKHR) {
23112329 // 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+ }
23162336 }
23172337 }
23182338 break ;
@@ -2323,11 +2343,13 @@ spv_result_t CheckInvalidVulkanExplicitLayout(ValidationState_t& vstate) {
23232343 if (ptr_type->opcode () == spv::Op::OpTypeUntypedPointerKHR) {
23242344 // For untyped pointers, check the type of the data operand for an
23252345 // 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+ }
23312353 }
23322354 }
23332355 break ;
@@ -2339,7 +2361,10 @@ spv_result_t CheckInvalidVulkanExplicitLayout(ValidationState_t& vstate) {
23392361 return vstate.diag (SPV_ERROR_INVALID_ID, &inst)
23402362 << vstate.VkErrorID (10684 )
23412363 << " 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." ;
23432368 }
23442369 }
23452370
0 commit comments