@@ -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,15 +2271,15 @@ 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) ) {
2281+ layout_dec = UsesExplicitLayout ( vstate, check_id, cache);
2282+ if (! AllowsLayout ( vstate, sc) && layout_dec != spv::Decoration::Max ) {
22732283 fail_id = check_id;
22742284 }
22752285 break ;
@@ -2280,13 +2290,17 @@ spv_result_t CheckInvalidVulkanExplicitLayout(ValidationState_t& vstate) {
22802290 case spv::Op::OpUntypedInBoundsPtrAccessChainKHR: {
22812291 // Check both the base type and return type. The return type may have an
22822292 // invalid array stride.
2283- const auto sc = type_inst->GetOperandAs <spv::StorageClass>(1 );
2293+ sc = type_inst->GetOperandAs <spv::StorageClass>(1 );
22842294 const auto base_type_id = inst.GetOperandAs <uint32_t >(2 );
22852295 if (!AllowsLayout (vstate, sc)) {
2286- if (UsesExplicitLayout (vstate, base_type_id, cache)) {
2296+ layout_dec = UsesExplicitLayout (vstate, base_type_id, cache);
2297+ if (layout_dec != spv::Decoration::Max) {
22872298 fail_id = base_type_id;
2288- } else if (UsesExplicitLayout (vstate, type_id, cache)) {
2289- fail_id = type_id;
2299+ } else {
2300+ layout_dec = UsesExplicitLayout (vstate, type_id, cache);
2301+ if (layout_dec != spv::Decoration::Max) {
2302+ fail_id = type_id;
2303+ }
22902304 }
22912305 }
22922306 break ;
@@ -2296,10 +2310,10 @@ spv_result_t CheckInvalidVulkanExplicitLayout(ValidationState_t& vstate) {
22962310 const auto ptr_ty_id =
22972311 vstate.FindDef (inst.GetOperandAs <uint32_t >(3 ))->type_id ();
22982312 const auto ptr_ty = vstate.FindDef (ptr_ty_id);
2299- const auto sc = ptr_ty->GetOperandAs <spv::StorageClass>(1 );
2313+ sc = ptr_ty->GetOperandAs <spv::StorageClass>(1 );
23002314 const auto base_type_id = inst.GetOperandAs <uint32_t >(2 );
2301- if (! AllowsLayout ( vstate, sc) &&
2302- UsesExplicitLayout ( vstate, base_type_id, cache) ) {
2315+ layout_dec = UsesExplicitLayout ( vstate, base_type_id, cache);
2316+ if (! AllowsLayout ( vstate, sc) && layout_dec != spv::Decoration::Max ) {
23032317 fail_id = base_type_id;
23042318 }
23052319 break ;
@@ -2309,9 +2323,9 @@ spv_result_t CheckInvalidVulkanExplicitLayout(ValidationState_t& vstate) {
23092323 const auto ptr_type = vstate.FindDef (vstate.FindDef (ptr_id)->type_id ());
23102324 if (ptr_type->opcode () == spv::Op::OpTypeUntypedPointerKHR) {
23112325 // 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) ) {
2326+ sc = ptr_type->GetOperandAs <spv::StorageClass>(1 );
2327+ layout_dec = UsesExplicitLayout ( vstate, type_id, cache);
2328+ if (! AllowsLayout ( vstate, sc) && layout_dec != spv::Decoration::Max ) {
23152329 fail_id = type_id;
23162330 }
23172331 }
@@ -2323,10 +2337,10 @@ spv_result_t CheckInvalidVulkanExplicitLayout(ValidationState_t& vstate) {
23232337 if (ptr_type->opcode () == spv::Op::OpTypeUntypedPointerKHR) {
23242338 // For untyped pointers, check the type of the data operand for an
23252339 // invalid layout.
2326- const auto sc = ptr_type->GetOperandAs <spv::StorageClass>(1 );
2340+ sc = ptr_type->GetOperandAs <spv::StorageClass>(1 );
23272341 const auto data_type_id = vstate.GetOperandTypeId (&inst, 1 );
2328- if (! AllowsLayout ( vstate, sc) &&
2329- UsesExplicitLayout ( vstate, data_type_id, cache) ) {
2342+ layout_dec = UsesExplicitLayout ( vstate, data_type_id, cache);
2343+ if (! AllowsLayout ( vstate, sc) && layout_dec != spv::Decoration::Max ) {
23302344 fail_id = inst.GetOperandAs <uint32_t >(2 );
23312345 }
23322346 }
@@ -2339,7 +2353,10 @@ spv_result_t CheckInvalidVulkanExplicitLayout(ValidationState_t& vstate) {
23392353 return vstate.diag (SPV_ERROR_INVALID_ID, &inst)
23402354 << vstate.VkErrorID (10684 )
23412355 << " Invalid explicit layout decorations on type for operand "
2342- << vstate.getIdName (fail_id);
2356+ << vstate.getIdName (fail_id) << " , the "
2357+ << spvtools::StorageClassToString (sc)
2358+ << " storage class has a explicit layout from the "
2359+ << vstate.SpvDecorationString (layout_dec) << " decoration." ;
23432360 }
23442361 }
23452362
0 commit comments