Skip to content

Commit 61c51d4

Browse files
spirv-val: Add Mesh Primitive Built-In validaiton (KhronosGroup#5529)
1 parent 5d3c8b7 commit 61c51d4

File tree

3 files changed

+449
-3
lines changed

3 files changed

+449
-3
lines changed

source/val/validate_builtins.cpp

Lines changed: 177 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,15 @@ typedef enum VUIDError_ {
118118
VUIDErrorMax,
119119
} VUIDError;
120120

121-
const static uint32_t NumVUIDBuiltins = 36;
121+
const static uint32_t NumVUIDBuiltins = 39;
122122

123123
typedef struct {
124124
spv::BuiltIn builtIn;
125125
uint32_t vuid[VUIDErrorMax]; // execution mode, storage class, type VUIDs
126126
} BuiltinVUIDMapping;
127127

128+
// Many built-ins have the same checks (Storage Class, Type, etc)
129+
// This table provides a nice LUT for the VUIDs
128130
std::array<BuiltinVUIDMapping, NumVUIDBuiltins> builtinVUIDInfo = {{
129131
// clang-format off
130132
{spv::BuiltIn::SubgroupEqMask, {0, 4370, 4371}},
@@ -163,8 +165,11 @@ std::array<BuiltinVUIDMapping, NumVUIDBuiltins> builtinVUIDInfo = {{
163165
{spv::BuiltIn::CullMaskKHR, {6735, 6736, 6737}},
164166
{spv::BuiltIn::BaryCoordKHR, {4154, 4155, 4156}},
165167
{spv::BuiltIn::BaryCoordNoPerspKHR, {4160, 4161, 4162}},
166-
// clang-format off
167-
} };
168+
{spv::BuiltIn::PrimitivePointIndicesEXT, {7041, 7043, 7044}},
169+
{spv::BuiltIn::PrimitiveLineIndicesEXT, {7047, 7049, 7050}},
170+
{spv::BuiltIn::PrimitiveTriangleIndicesEXT, {7053, 7055, 7056}},
171+
// clang-format on
172+
}};
168173

169174
uint32_t GetVUIDForBuiltin(spv::BuiltIn builtIn, VUIDError type) {
170175
uint32_t vuid = 0;
@@ -356,6 +361,9 @@ class BuiltInsValidator {
356361
spv_result_t ValidateRayTracingBuiltinsAtDefinition(
357362
const Decoration& decoration, const Instruction& inst);
358363

364+
spv_result_t ValidateMeshShadingEXTBuiltinsAtDefinition(
365+
const Decoration& decoration, const Instruction& inst);
366+
359367
// The following section contains functions which are called when id defined
360368
// by |referenced_inst| is
361369
// 1. referenced by |referenced_from_inst|
@@ -546,6 +554,11 @@ class BuiltInsValidator {
546554
const Instruction& referenced_inst,
547555
const Instruction& referenced_from_inst);
548556

557+
spv_result_t ValidateMeshShadingEXTBuiltinsAtReference(
558+
const Decoration& decoration, const Instruction& built_in_inst,
559+
const Instruction& referenced_inst,
560+
const Instruction& referenced_from_inst);
561+
549562
// Validates that |built_in_inst| is not (even indirectly) referenced from
550563
// within a function which can be called with |execution_model|.
551564
//
@@ -581,6 +594,10 @@ class BuiltInsValidator {
581594
spv_result_t ValidateI32Arr(
582595
const Decoration& decoration, const Instruction& inst,
583596
const std::function<spv_result_t(const std::string& message)>& diag);
597+
spv_result_t ValidateArrayedI32Vec(
598+
const Decoration& decoration, const Instruction& inst,
599+
uint32_t num_components,
600+
const std::function<spv_result_t(const std::string& message)>& diag);
584601
spv_result_t ValidateOptionalArrayedI32(
585602
const Decoration& decoration, const Instruction& inst,
586603
const std::function<spv_result_t(const std::string& message)>& diag);
@@ -909,6 +926,45 @@ spv_result_t BuiltInsValidator::ValidateI32Vec(
909926
return SPV_SUCCESS;
910927
}
911928

929+
spv_result_t BuiltInsValidator::ValidateArrayedI32Vec(
930+
const Decoration& decoration, const Instruction& inst,
931+
uint32_t num_components,
932+
const std::function<spv_result_t(const std::string& message)>& diag) {
933+
uint32_t underlying_type = 0;
934+
if (spv_result_t error =
935+
GetUnderlyingType(_, decoration, inst, &underlying_type)) {
936+
return error;
937+
}
938+
939+
const Instruction* const type_inst = _.FindDef(underlying_type);
940+
if (type_inst->opcode() != spv::Op::OpTypeArray) {
941+
return diag(GetDefinitionDesc(decoration, inst) + " is not an array.");
942+
}
943+
944+
const uint32_t component_type = type_inst->word(2);
945+
if (!_.IsIntVectorType(component_type)) {
946+
return diag(GetDefinitionDesc(decoration, inst) + " is not an int vector.");
947+
}
948+
949+
const uint32_t actual_num_components = _.GetDimension(component_type);
950+
if (_.GetDimension(component_type) != num_components) {
951+
std::ostringstream ss;
952+
ss << GetDefinitionDesc(decoration, inst) << " has "
953+
<< actual_num_components << " components.";
954+
return diag(ss.str());
955+
}
956+
957+
const uint32_t bit_width = _.GetBitWidth(component_type);
958+
if (bit_width != 32) {
959+
std::ostringstream ss;
960+
ss << GetDefinitionDesc(decoration, inst)
961+
<< " has components with bit width " << bit_width << ".";
962+
return diag(ss.str());
963+
}
964+
965+
return SPV_SUCCESS;
966+
}
967+
912968
spv_result_t BuiltInsValidator::ValidateOptionalArrayedF32Vec(
913969
const Decoration& decoration, const Instruction& inst,
914970
uint32_t num_components,
@@ -4108,6 +4164,119 @@ spv_result_t BuiltInsValidator::ValidateRayTracingBuiltinsAtReference(
41084164
return SPV_SUCCESS;
41094165
}
41104166

4167+
spv_result_t BuiltInsValidator::ValidateMeshShadingEXTBuiltinsAtDefinition(
4168+
const Decoration& decoration, const Instruction& inst) {
4169+
if (spvIsVulkanEnv(_.context()->target_env)) {
4170+
const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
4171+
uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
4172+
if (builtin == spv::BuiltIn::PrimitivePointIndicesEXT) {
4173+
if (spv_result_t error = ValidateI32Arr(
4174+
decoration, inst,
4175+
[this, &inst, &decoration,
4176+
&vuid](const std::string& message) -> spv_result_t {
4177+
return _.diag(SPV_ERROR_INVALID_DATA, &inst)
4178+
<< _.VkErrorID(vuid) << "According to the "
4179+
<< spvLogStringForEnv(_.context()->target_env)
4180+
<< " spec BuiltIn "
4181+
<< _.grammar().lookupOperandName(
4182+
SPV_OPERAND_TYPE_BUILT_IN, decoration.params()[0])
4183+
<< " variable needs to be a 32-bit int array."
4184+
<< message;
4185+
})) {
4186+
return error;
4187+
}
4188+
}
4189+
if (builtin == spv::BuiltIn::PrimitiveLineIndicesEXT) {
4190+
if (spv_result_t error = ValidateArrayedI32Vec(
4191+
decoration, inst, 2,
4192+
[this, &inst, &decoration,
4193+
&vuid](const std::string& message) -> spv_result_t {
4194+
return _.diag(SPV_ERROR_INVALID_DATA, &inst)
4195+
<< _.VkErrorID(vuid) << "According to the "
4196+
<< spvLogStringForEnv(_.context()->target_env)
4197+
<< " spec BuiltIn "
4198+
<< _.grammar().lookupOperandName(
4199+
SPV_OPERAND_TYPE_BUILT_IN, decoration.params()[0])
4200+
<< " variable needs to be a 2-component 32-bit int "
4201+
"array."
4202+
<< message;
4203+
})) {
4204+
return error;
4205+
}
4206+
}
4207+
if (builtin == spv::BuiltIn::PrimitiveTriangleIndicesEXT) {
4208+
if (spv_result_t error = ValidateArrayedI32Vec(
4209+
decoration, inst, 3,
4210+
[this, &inst, &decoration,
4211+
&vuid](const std::string& message) -> spv_result_t {
4212+
return _.diag(SPV_ERROR_INVALID_DATA, &inst)
4213+
<< _.VkErrorID(vuid) << "According to the "
4214+
<< spvLogStringForEnv(_.context()->target_env)
4215+
<< " spec BuiltIn "
4216+
<< _.grammar().lookupOperandName(
4217+
SPV_OPERAND_TYPE_BUILT_IN, decoration.params()[0])
4218+
<< " variable needs to be a 3-component 32-bit int "
4219+
"array."
4220+
<< message;
4221+
})) {
4222+
return error;
4223+
}
4224+
}
4225+
}
4226+
// Seed at reference checks with this built-in.
4227+
return ValidateMeshShadingEXTBuiltinsAtReference(decoration, inst, inst,
4228+
inst);
4229+
}
4230+
4231+
spv_result_t BuiltInsValidator::ValidateMeshShadingEXTBuiltinsAtReference(
4232+
const Decoration& decoration, const Instruction& built_in_inst,
4233+
const Instruction& referenced_inst,
4234+
const Instruction& referenced_from_inst) {
4235+
if (spvIsVulkanEnv(_.context()->target_env)) {
4236+
const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
4237+
const spv::StorageClass storage_class =
4238+
GetStorageClass(referenced_from_inst);
4239+
if (storage_class != spv::StorageClass::Max &&
4240+
storage_class != spv::StorageClass::Output) {
4241+
uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
4242+
return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
4243+
<< _.VkErrorID(vuid) << spvLogStringForEnv(_.context()->target_env)
4244+
<< " spec allows BuiltIn "
4245+
<< _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
4246+
uint32_t(builtin))
4247+
<< " to be only used for variables with Output storage class. "
4248+
<< GetReferenceDesc(decoration, built_in_inst, referenced_inst,
4249+
referenced_from_inst)
4250+
<< " " << GetStorageClassDesc(referenced_from_inst);
4251+
}
4252+
4253+
for (const spv::ExecutionModel execution_model : execution_models_) {
4254+
if (execution_model != spv::ExecutionModel::MeshEXT) {
4255+
uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
4256+
return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
4257+
<< _.VkErrorID(vuid)
4258+
<< spvLogStringForEnv(_.context()->target_env)
4259+
<< " spec allows BuiltIn "
4260+
<< _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
4261+
uint32_t(builtin))
4262+
<< " to be used only with MeshEXT execution model. "
4263+
<< GetReferenceDesc(decoration, built_in_inst, referenced_inst,
4264+
referenced_from_inst, execution_model);
4265+
}
4266+
}
4267+
}
4268+
4269+
if (function_id_ == 0) {
4270+
// Propagate this rule to all dependant ids in the global scope.
4271+
id_to_at_reference_checks_[referenced_from_inst.id()].push_back(
4272+
std::bind(&BuiltInsValidator::ValidateMeshShadingEXTBuiltinsAtReference,
4273+
this, decoration, built_in_inst, referenced_from_inst,
4274+
std::placeholders::_1));
4275+
}
4276+
4277+
return SPV_SUCCESS;
4278+
}
4279+
41114280
spv_result_t BuiltInsValidator::ValidateSingleBuiltInAtDefinition(
41124281
const Decoration& decoration, const Instruction& inst) {
41134282
const spv::BuiltIn label = spv::BuiltIn(decoration.params()[0]);
@@ -4283,6 +4452,11 @@ spv_result_t BuiltInsValidator::ValidateSingleBuiltInAtDefinition(
42834452
case spv::BuiltIn::CullMaskKHR: {
42844453
return ValidateRayTracingBuiltinsAtDefinition(decoration, inst);
42854454
}
4455+
case spv::BuiltIn::PrimitivePointIndicesEXT:
4456+
case spv::BuiltIn::PrimitiveLineIndicesEXT:
4457+
case spv::BuiltIn::PrimitiveTriangleIndicesEXT: {
4458+
return ValidateMeshShadingEXTBuiltinsAtDefinition(decoration, inst);
4459+
}
42864460
case spv::BuiltIn::PrimitiveShadingRateKHR: {
42874461
return ValidatePrimitiveShadingRateAtDefinition(decoration, inst);
42884462
}

source/val/validation_state.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2259,6 +2259,24 @@ std::string ValidationState_t::VkErrorID(uint32_t id,
22592259
return VUID_WRAP(VUID-StandaloneSpirv-PushConstant-06808);
22602260
case 6925:
22612261
return VUID_WRAP(VUID-StandaloneSpirv-Uniform-06925);
2262+
case 7041:
2263+
return VUID_WRAP(VUID-PrimitivePointIndicesEXT-PrimitivePointIndicesEXT-07041);
2264+
case 7043:
2265+
return VUID_WRAP(VUID-PrimitivePointIndicesEXT-PrimitivePointIndicesEXT-07043);
2266+
case 7044:
2267+
return VUID_WRAP(VUID-PrimitivePointIndicesEXT-PrimitivePointIndicesEXT-07044);
2268+
case 7047:
2269+
return VUID_WRAP(VUID-PrimitiveLineIndicesEXT-PrimitiveLineIndicesEXT-07047);
2270+
case 7049:
2271+
return VUID_WRAP(VUID-PrimitiveLineIndicesEXT-PrimitiveLineIndicesEXT-07049);
2272+
case 7050:
2273+
return VUID_WRAP(VUID-PrimitiveLineIndicesEXT-PrimitiveLineIndicesEXT-07050);
2274+
case 7053:
2275+
return VUID_WRAP(VUID-PrimitiveTriangleIndicesEXT-PrimitiveTriangleIndicesEXT-07053);
2276+
case 7055:
2277+
return VUID_WRAP(VUID-PrimitiveTriangleIndicesEXT-PrimitiveTriangleIndicesEXT-07055);
2278+
case 7056:
2279+
return VUID_WRAP(VUID-PrimitiveTriangleIndicesEXT-PrimitiveTriangleIndicesEXT-07056);
22622280
case 7102:
22632281
return VUID_WRAP(VUID-StandaloneSpirv-MeshEXT-07102);
22642282
case 7320:

0 commit comments

Comments
 (0)