Skip to content

Commit 723fede

Browse files
spirv-val: Improve Explicit Layout message
1 parent 6ce15eb commit 723fede

File tree

3 files changed

+117
-32
lines changed

3 files changed

+117
-32
lines changed

source/table2.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,4 +372,69 @@ bool GetExtensionFromString(const char* name, Extension* extension) {
372372
return false;
373373
}
374374

375+
// This is dirty copy of the spirv.hpp11 function
376+
// TODO - Use a generated version of this function
377+
const char* StorageClassToString(spv::StorageClass value) {
378+
switch (value) {
379+
case spv::StorageClass::UniformConstant:
380+
return "UniformConstant";
381+
case spv::StorageClass::Input:
382+
return "Input";
383+
case spv::StorageClass::Uniform:
384+
return "Uniform";
385+
case spv::StorageClass::Output:
386+
return "Output";
387+
case spv::StorageClass::Workgroup:
388+
return "Workgroup";
389+
case spv::StorageClass::CrossWorkgroup:
390+
return "CrossWorkgroup";
391+
case spv::StorageClass::Private:
392+
return "Private";
393+
case spv::StorageClass::Function:
394+
return "Function";
395+
case spv::StorageClass::Generic:
396+
return "Generic";
397+
case spv::StorageClass::PushConstant:
398+
return "PushConstant";
399+
case spv::StorageClass::AtomicCounter:
400+
return "AtomicCounter";
401+
case spv::StorageClass::Image:
402+
return "Image";
403+
case spv::StorageClass::StorageBuffer:
404+
return "StorageBuffer";
405+
case spv::StorageClass::TileImageEXT:
406+
return "TileImageEXT";
407+
case spv::StorageClass::TileAttachmentQCOM:
408+
return "TileAttachmentQCOM";
409+
case spv::StorageClass::NodePayloadAMDX:
410+
return "NodePayloadAMDX";
411+
case spv::StorageClass::CallableDataKHR:
412+
return "CallableDataKHR";
413+
case spv::StorageClass::IncomingCallableDataKHR:
414+
return "IncomingCallableDataKHR";
415+
case spv::StorageClass::RayPayloadKHR:
416+
return "RayPayloadKHR";
417+
case spv::StorageClass::HitAttributeKHR:
418+
return "HitAttributeKHR";
419+
case spv::StorageClass::IncomingRayPayloadKHR:
420+
return "IncomingRayPayloadKHR";
421+
case spv::StorageClass::ShaderRecordBufferKHR:
422+
return "ShaderRecordBufferKHR";
423+
case spv::StorageClass::PhysicalStorageBuffer:
424+
return "PhysicalStorageBuffer";
425+
case spv::StorageClass::HitObjectAttributeNV:
426+
return "HitObjectAttributeNV";
427+
case spv::StorageClass::TaskPayloadWorkgroupEXT:
428+
return "TaskPayloadWorkgroupEXT";
429+
case spv::StorageClass::CodeSectionINTEL:
430+
return "CodeSectionINTEL";
431+
case spv::StorageClass::DeviceOnlyINTEL:
432+
return "DeviceOnlyINTEL";
433+
case spv::StorageClass::HostOnlyINTEL:
434+
return "HostOnlyINTEL";
435+
default:
436+
return "Unknown";
437+
}
438+
}
439+
375440
} // namespace spvtools

source/table2.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,5 +256,8 @@ bool GetExtensionFromString(const char* str, Extension* extension);
256256
// Returns text string corresponding to |extension|.
257257
const char* ExtensionToString(Extension extension);
258258

259+
/// Used to provide better error message
260+
const char* StorageClassToString(spv::StorageClass value);
261+
259262
} // namespace spvtools
260263
#endif // SOURCE_TABLE2_H_

source/val/validate_decorations.cpp

Lines changed: 49 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)