spirv-val: Add Vulkan EXT builtins (#4115)
diff --git a/source/val/validate_builtins.cpp b/source/val/validate_builtins.cpp
index 7fb9908..3c9df9f 100644
--- a/source/val/validate_builtins.cpp
+++ b/source/val/validate_builtins.cpp
@@ -120,7 +120,7 @@
VUIDErrorMax,
} VUIDError;
-const static uint32_t NumVUIDBuiltins = 29;
+const static uint32_t NumVUIDBuiltins = 33;
typedef struct {
SpvBuiltIn builtIn;
@@ -158,6 +158,10 @@
{SpvBuiltInWorldRayOriginKHR, {4431, 4432, 4433}},
{SpvBuiltInLaunchIdKHR, {4266, 4267, 4268}},
{SpvBuiltInLaunchSizeKHR, {4269, 4270, 4271}},
+ {SpvBuiltInFragInvocationCountEXT, {4217, 4218, 4219}},
+ {SpvBuiltInFragSizeEXT, {4220, 4221, 4222}},
+ {SpvBuiltInFragStencilRefEXT, {4223, 4224, 4225}},
+ {SpvBuiltInFullyCoveredEXT, {4232, 4233, 4234}},
// clang-format off
} };
@@ -314,6 +318,14 @@
const Instruction& inst);
spv_result_t ValidateDeviceIndexAtDefinition(const Decoration& decoration,
const Instruction& inst);
+ spv_result_t ValidateFragInvocationCountAtDefinition(const Decoration& decoration,
+ const Instruction& inst);
+ spv_result_t ValidateFragSizeAtDefinition(const Decoration& decoration,
+ const Instruction& inst);
+ spv_result_t ValidateFragStencilRefAtDefinition(const Decoration& decoration,
+ const Instruction& inst);
+ spv_result_t ValidateFullyCoveredAtDefinition(const Decoration& decoration,
+ const Instruction& inst);
// Used for GlobalInvocationId, LocalInvocationId, NumWorkgroups, WorkgroupId.
spv_result_t ValidateComputeShaderI32Vec3InputAtDefinition(
const Decoration& decoration, const Instruction& inst);
@@ -472,6 +484,26 @@
const Instruction& referenced_inst,
const Instruction& referenced_from_inst);
+ spv_result_t ValidateFragInvocationCountAtReference(
+ const Decoration& decoration, const Instruction& built_in_inst,
+ const Instruction& referenced_inst,
+ const Instruction& referenced_from_inst);
+
+ spv_result_t ValidateFragSizeAtReference(
+ const Decoration& decoration, const Instruction& built_in_inst,
+ const Instruction& referenced_inst,
+ const Instruction& referenced_from_inst);
+
+ spv_result_t ValidateFragStencilRefAtReference(
+ const Decoration& decoration, const Instruction& built_in_inst,
+ const Instruction& referenced_inst,
+ const Instruction& referenced_from_inst);
+
+ spv_result_t ValidateFullyCoveredAtReference(
+ const Decoration& decoration, const Instruction& built_in_inst,
+ const Instruction& referenced_inst,
+ const Instruction& referenced_from_inst);
+
// Used for GlobalInvocationId, LocalInvocationId, NumWorkgroups, WorkgroupId.
spv_result_t ValidateComputeShaderI32Vec3InputAtReference(
const Decoration& decoration, const Instruction& built_in_inst,
@@ -525,6 +557,9 @@
spv_result_t ValidateBool(
const Decoration& decoration, const Instruction& inst,
const std::function<spv_result_t(const std::string& message)>& diag);
+ spv_result_t ValidateI(
+ const Decoration& decoration, const Instruction& inst,
+ const std::function<spv_result_t(const std::string& message)>& diag);
spv_result_t ValidateI32(
const Decoration& decoration, const Instruction& inst,
const std::function<spv_result_t(const std::string& message)>& diag);
@@ -717,6 +752,22 @@
return SPV_SUCCESS;
}
+spv_result_t BuiltInsValidator::ValidateI(
+ const Decoration& decoration, const Instruction& inst,
+ const std::function<spv_result_t(const std::string& message)>& diag) {
+ uint32_t underlying_type = 0;
+ if (spv_result_t error =
+ GetUnderlyingType(_, decoration, inst, &underlying_type)) {
+ return error;
+ }
+
+ if (!_.IsIntScalarType(underlying_type)) {
+ return diag(GetDefinitionDesc(decoration, inst) + " is not an int scalar.");
+ }
+
+ return SPV_SUCCESS;
+}
+
spv_result_t BuiltInsValidator::ValidateI32(
const Decoration& decoration, const Instruction& inst,
const std::function<spv_result_t(const std::string& message)>& diag) {
@@ -3296,6 +3347,287 @@
return SPV_SUCCESS;
}
+spv_result_t BuiltInsValidator::ValidateFragInvocationCountAtDefinition(const Decoration& decoration,
+ const Instruction& inst) {
+
+ if (spvIsVulkanEnv(_.context()->target_env)) {
+ const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+ if (spv_result_t error = ValidateI32(
+ decoration, inst,
+ [this, &inst, &builtin](const std::string& message) -> spv_result_t {
+ uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
+ return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+ << _.VkErrorID(vuid) << "According to the "
+ << spvLogStringForEnv(_.context()->target_env)
+ << " spec BuiltIn "
+ << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
+ builtin)
+ << " variable needs to be a 32-bit int scalar. "
+ << message;
+ })) {
+ return error;
+ }
+ }
+
+ return ValidateFragInvocationCountAtReference(decoration, inst, inst, inst);
+}
+
+spv_result_t BuiltInsValidator::ValidateFragInvocationCountAtReference(
+ const Decoration& decoration, const Instruction& built_in_inst,
+ const Instruction& referenced_inst,
+ const Instruction& referenced_from_inst) {
+
+ if (spvIsVulkanEnv(_.context()->target_env)) {
+ const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+ const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
+ if (storage_class != SpvStorageClassMax &&
+ storage_class != SpvStorageClassInput) {
+ uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
+ return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+ << _.VkErrorID(vuid) << spvLogStringForEnv(_.context()->target_env)
+ << " spec allows BuiltIn "
+ << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+ << " to be only used for variables with Input storage class. "
+ << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
+ referenced_from_inst)
+ << " " << GetStorageClassDesc(referenced_from_inst);
+ }
+
+ for (const SpvExecutionModel execution_model : execution_models_) {
+ if (execution_model != SpvExecutionModelFragment) {
+ uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
+ return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+ << _.VkErrorID(vuid)
+ << spvLogStringForEnv(_.context()->target_env)
+ << " spec allows BuiltIn "
+ << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+ << " to be used only with Fragment execution model. "
+ << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
+ referenced_from_inst, execution_model);
+ }
+ }
+ }
+
+ if (function_id_ == 0) {
+ // Propagate this rule to all dependant ids in the global scope.
+ id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
+ &BuiltInsValidator::ValidateFragInvocationCountAtReference, this, decoration,
+ built_in_inst, referenced_from_inst, std::placeholders::_1));
+ }
+
+ return SPV_SUCCESS;
+}
+
+spv_result_t BuiltInsValidator::ValidateFragSizeAtDefinition(const Decoration& decoration,
+ const Instruction& inst) {
+ if (spvIsVulkanEnv(_.context()->target_env)) {
+ const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+ if (spv_result_t error = ValidateI32Vec(
+ decoration, inst, 2,
+ [this, &inst, &builtin](const std::string& message) -> spv_result_t {
+ uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
+ return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+ << _.VkErrorID(vuid) << "According to the "
+ << spvLogStringForEnv(_.context()->target_env)
+ << " spec BuiltIn "
+ << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
+ builtin)
+ << " variable needs to be a 2-component 32-bit int vector. "
+ << message;
+ })) {
+ return error;
+ }
+ }
+
+ return ValidateFragSizeAtReference(decoration, inst, inst, inst);
+}
+
+spv_result_t BuiltInsValidator::ValidateFragSizeAtReference(
+ const Decoration& decoration, const Instruction& built_in_inst,
+ const Instruction& referenced_inst,
+ const Instruction& referenced_from_inst) {
+
+ if (spvIsVulkanEnv(_.context()->target_env)) {
+ const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+ const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
+ if (storage_class != SpvStorageClassMax &&
+ storage_class != SpvStorageClassInput) {
+ uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
+ return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+ << _.VkErrorID(vuid) << spvLogStringForEnv(_.context()->target_env)
+ << " spec allows BuiltIn "
+ << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+ << " to be only used for variables with Input storage class. "
+ << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
+ referenced_from_inst)
+ << " " << GetStorageClassDesc(referenced_from_inst);
+ }
+
+ for (const SpvExecutionModel execution_model : execution_models_) {
+ if (execution_model != SpvExecutionModelFragment) {
+ uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
+ return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+ << _.VkErrorID(vuid)
+ << spvLogStringForEnv(_.context()->target_env)
+ << " spec allows BuiltIn "
+ << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+ << " to be used only with Fragment execution model. "
+ << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
+ referenced_from_inst, execution_model);
+ }
+ }
+ }
+
+ if (function_id_ == 0) {
+ // Propagate this rule to all dependant ids in the global scope.
+ id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
+ &BuiltInsValidator::ValidateFragSizeAtReference, this, decoration,
+ built_in_inst, referenced_from_inst, std::placeholders::_1));
+ }
+
+ return SPV_SUCCESS;
+}
+
+spv_result_t BuiltInsValidator::ValidateFragStencilRefAtDefinition(const Decoration& decoration,
+ const Instruction& inst) {
+ if (spvIsVulkanEnv(_.context()->target_env)) {
+ const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+ if (spv_result_t error = ValidateI(
+ decoration, inst,
+ [this, &inst, &builtin](const std::string& message) -> spv_result_t {
+ uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
+ return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+ << _.VkErrorID(vuid) << "According to the "
+ << spvLogStringForEnv(_.context()->target_env)
+ << " spec BuiltIn "
+ << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
+ builtin)
+ << " variable needs to be a int scalar. "
+ << message;
+ })) {
+ return error;
+ }
+ }
+
+ return ValidateFragStencilRefAtReference(decoration, inst, inst, inst);
+}
+
+spv_result_t BuiltInsValidator::ValidateFragStencilRefAtReference(
+ const Decoration& decoration, const Instruction& built_in_inst,
+ const Instruction& referenced_inst,
+ const Instruction& referenced_from_inst) {
+
+ if (spvIsVulkanEnv(_.context()->target_env)) {
+ const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+ const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
+ if (storage_class != SpvStorageClassMax &&
+ storage_class != SpvStorageClassOutput) {
+ uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
+ return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+ << _.VkErrorID(vuid) << spvLogStringForEnv(_.context()->target_env)
+ << " spec allows BuiltIn "
+ << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+ << " to be only used for variables with Output storage class. "
+ << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
+ referenced_from_inst)
+ << " " << GetStorageClassDesc(referenced_from_inst);
+ }
+
+ for (const SpvExecutionModel execution_model : execution_models_) {
+ if (execution_model != SpvExecutionModelFragment) {
+ uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
+ return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+ << _.VkErrorID(vuid)
+ << spvLogStringForEnv(_.context()->target_env)
+ << " spec allows BuiltIn "
+ << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+ << " to be used only with Fragment execution model. "
+ << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
+ referenced_from_inst, execution_model);
+ }
+ }
+ }
+
+ if (function_id_ == 0) {
+ // Propagate this rule to all dependant ids in the global scope.
+ id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
+ &BuiltInsValidator::ValidateFragStencilRefAtReference, this, decoration,
+ built_in_inst, referenced_from_inst, std::placeholders::_1));
+ }
+
+ return SPV_SUCCESS;
+}
+
+spv_result_t BuiltInsValidator::ValidateFullyCoveredAtDefinition(const Decoration& decoration,
+ const Instruction& inst) {
+ if (spvIsVulkanEnv(_.context()->target_env)) {
+ const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+ if (spv_result_t error = ValidateBool(
+ decoration, inst,
+ [this, &inst, &builtin](const std::string& message) -> spv_result_t {
+ uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
+ return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+ << _.VkErrorID(vuid) << "According to the "
+ << spvLogStringForEnv(_.context()->target_env)
+ << " spec BuiltIn "
+ << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
+ builtin)
+ << " variable needs to be a bool scalar. "
+ << message;
+ })) {
+ return error;
+ }
+ }
+
+ return ValidateFullyCoveredAtReference(decoration, inst, inst, inst);
+}
+
+spv_result_t BuiltInsValidator::ValidateFullyCoveredAtReference(
+ const Decoration& decoration, const Instruction& built_in_inst,
+ const Instruction& referenced_inst,
+ const Instruction& referenced_from_inst) {
+
+ if (spvIsVulkanEnv(_.context()->target_env)) {
+ const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+ const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
+ if (storage_class != SpvStorageClassMax &&
+ storage_class != SpvStorageClassInput) {
+ uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
+ return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+ << _.VkErrorID(vuid) << spvLogStringForEnv(_.context()->target_env)
+ << " spec allows BuiltIn "
+ << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+ << " to be only used for variables with Input storage class. "
+ << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
+ referenced_from_inst)
+ << " " << GetStorageClassDesc(referenced_from_inst);
+ }
+
+ for (const SpvExecutionModel execution_model : execution_models_) {
+ if (execution_model != SpvExecutionModelFragment) {
+ uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
+ return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+ << _.VkErrorID(vuid)
+ << spvLogStringForEnv(_.context()->target_env)
+ << " spec allows BuiltIn "
+ << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+ << " to be used only with Fragment execution model. "
+ << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
+ referenced_from_inst, execution_model);
+ }
+ }
+ }
+
+ if (function_id_ == 0) {
+ // Propagate this rule to all dependant ids in the global scope.
+ id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
+ &BuiltInsValidator::ValidateFullyCoveredAtReference, this, decoration,
+ built_in_inst, referenced_from_inst, std::placeholders::_1));
+ }
+
+ return SPV_SUCCESS;
+}
+
spv_result_t BuiltInsValidator::ValidateSMBuiltinsAtDefinition(
const Decoration& decoration, const Instruction& inst) {
if (spvIsVulkanEnv(_.context()->target_env)) {
@@ -3793,6 +4125,20 @@
case SpvBuiltInDeviceIndex: {
return ValidateDeviceIndexAtDefinition(decoration, inst);
}
+ case SpvBuiltInFragInvocationCountEXT: {
+ // alias SpvBuiltInInvocationsPerPixelNV
+ return ValidateFragInvocationCountAtDefinition(decoration, inst);
+ }
+ case SpvBuiltInFragSizeEXT: {
+ // alias SpvBuiltInFragmentSizeNV
+ return ValidateFragSizeAtDefinition(decoration, inst);
+ }
+ case SpvBuiltInFragStencilRefEXT: {
+ return ValidateFragStencilRefAtDefinition(decoration, inst);
+ }
+ case SpvBuiltInFullyCoveredEXT:{
+ return ValidateFullyCoveredAtDefinition(decoration, inst);
+ }
// Ray tracing builtins
case SpvBuiltInHitKindKHR: // alias SpvBuiltInHitKindNV
case SpvBuiltInHitTNV: // NOT present in KHR
@@ -3828,13 +4174,11 @@
case SpvBuiltInBaryCoordSmoothCentroidAMD:
case SpvBuiltInBaryCoordSmoothSampleAMD:
case SpvBuiltInBaryCoordPullModelAMD:
- case SpvBuiltInFragStencilRefEXT:
case SpvBuiltInViewportMaskNV:
case SpvBuiltInSecondaryPositionNV:
case SpvBuiltInSecondaryViewportMaskNV:
case SpvBuiltInPositionPerViewNV:
case SpvBuiltInViewportMaskPerViewNV:
- case SpvBuiltInFullyCoveredEXT:
case SpvBuiltInMax:
case SpvBuiltInTaskCountNV:
case SpvBuiltInPrimitiveCountNV:
@@ -3846,9 +4190,6 @@
case SpvBuiltInMeshViewIndicesNV:
case SpvBuiltInBaryCoordNV:
case SpvBuiltInBaryCoordNoPerspNV:
- case SpvBuiltInFragmentSizeNV: // alias SpvBuiltInFragSizeEXT
- case SpvBuiltInInvocationsPerPixelNV: // alias
- // SpvBuiltInFragInvocationCountEXT
// No validation rules (for the moment).
break;
diff --git a/source/val/validation_state.cpp b/source/val/validation_state.cpp
index 92b51c7..b9269db 100644
--- a/source/val/validation_state.cpp
+++ b/source/val/validation_state.cpp
@@ -1340,12 +1340,36 @@
return VUID_WRAP(VUID-FragDepth-FragDepth-04215);
case 4216:
return VUID_WRAP(VUID-FragDepth-FragDepth-04216);
+ case 4217:
+ return VUID_WRAP(VUID-FragInvocationCountEXT-FragInvocationCountEXT-04217);
+ case 4218:
+ return VUID_WRAP(VUID-FragInvocationCountEXT-FragInvocationCountEXT-04218);
+ case 4219:
+ return VUID_WRAP(VUID-FragInvocationCountEXT-FragInvocationCountEXT-04219);
+ case 4220:
+ return VUID_WRAP(VUID-FragSizeEXT-FragSizeEXT-04220);
+ case 4221:
+ return VUID_WRAP(VUID-FragSizeEXT-FragSizeEXT-04221);
+ case 4222:
+ return VUID_WRAP(VUID-FragSizeEXT-FragSizeEXT-04222);
+ case 4223:
+ return VUID_WRAP(VUID-FragStencilRefEXT-FragStencilRefEXT-04223);
+ case 4224:
+ return VUID_WRAP(VUID-FragStencilRefEXT-FragStencilRefEXT-04224);
+ case 4225:
+ return VUID_WRAP(VUID-FragStencilRefEXT-FragStencilRefEXT-04225);
case 4229:
return VUID_WRAP(VUID-FrontFacing-FrontFacing-04229);
case 4230:
return VUID_WRAP(VUID-FrontFacing-FrontFacing-04230);
case 4231:
return VUID_WRAP(VUID-FrontFacing-FrontFacing-04231);
+ case 4232:
+ return VUID_WRAP(VUID-FullyCoveredEXT-FullyCoveredEXT-04232);
+ case 4233:
+ return VUID_WRAP(VUID-FullyCoveredEXT-FullyCoveredEXT-04233);
+ case 4234:
+ return VUID_WRAP(VUID-FullyCoveredEXT-FullyCoveredEXT-04234);
case 4236:
return VUID_WRAP(VUID-GlobalInvocationId-GlobalInvocationId-04236);
case 4237:
diff --git a/test/val/val_builtins_test.cpp b/test/val/val_builtins_test.cpp
index 66e73be..bbcdbb1 100644
--- a/test/val/val_builtins_test.cpp
+++ b/test/val/val_builtins_test.cpp
@@ -3941,6 +3941,184 @@
Values(TestResult(SPV_ERROR_INVALID_DATA,
"According to the Vulkan spec BuiltIn ShadingRateKHR "
"variable needs to be a 32-bit int scalar."))));
+
+INSTANTIATE_TEST_SUITE_P(
+ FragInvocationCountInputSuccess,
+ ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+ Combine(Values("FragInvocationCountEXT"), Values("Fragment"),
+ Values("Input"), Values("%u32"),
+ Values("OpCapability FragmentDensityEXT\n"),
+ Values("OpExtension \"SPV_EXT_fragment_invocation_density\"\n"),
+ Values(nullptr), Values(TestResult())));
+
+INSTANTIATE_TEST_SUITE_P(
+ FragInvocationCountInvalidExecutionModel,
+ ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+ Combine(
+ Values("FragInvocationCountEXT"), Values("Vertex"), Values("Input"),
+ Values("%u32"), Values("OpCapability FragmentDensityEXT\n"),
+ Values("OpExtension \"SPV_EXT_fragment_invocation_density\"\n"),
+ Values("VUID-FragInvocationCountEXT-FragInvocationCountEXT-04217"),
+ Values(TestResult(SPV_ERROR_INVALID_DATA,
+ "Vulkan spec allows BuiltIn FragInvocationCountEXT "
+ "to be used only with Fragment execution model."))));
+
+INSTANTIATE_TEST_SUITE_P(
+ FragInvocationCountInvalidStorageClass,
+ ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+ Combine(Values("FragInvocationCountEXT"), Values("Fragment"),
+ Values("Output"), Values("%u32"),
+ Values("OpCapability FragmentDensityEXT\n"),
+ Values("OpExtension \"SPV_EXT_fragment_invocation_density\"\n"),
+ Values("VUID-FragInvocationCountEXT-FragInvocationCountEXT-04218"),
+ Values(TestResult(
+ SPV_ERROR_INVALID_DATA,
+ "Vulkan spec allows BuiltIn FragInvocationCountEXT to be only "
+ "used for variables with Input storage class."))));
+
+INSTANTIATE_TEST_SUITE_P(
+ FragInvocationCountInvalidType,
+ ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+ Combine(Values("FragInvocationCountEXT"), Values("Fragment"),
+ Values("Input"), Values("%f32"),
+ Values("OpCapability FragmentDensityEXT\n"),
+ Values("OpExtension \"SPV_EXT_fragment_invocation_density\"\n"),
+ Values("VUID-FragInvocationCountEXT-FragInvocationCountEXT-04219"),
+ Values(TestResult(
+ SPV_ERROR_INVALID_DATA,
+ "According to the Vulkan spec BuiltIn FragInvocationCountEXT "
+ "variable needs to be a 32-bit int scalar."))));
+
+INSTANTIATE_TEST_SUITE_P(
+ FragSizeInputSuccess,
+ ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+ Combine(Values("FragSizeEXT"), Values("Fragment"), Values("Input"),
+ Values("%u32vec2"), Values("OpCapability FragmentDensityEXT\n"),
+ Values("OpExtension \"SPV_EXT_fragment_invocation_density\"\n"),
+ Values(nullptr), Values(TestResult())));
+
+INSTANTIATE_TEST_SUITE_P(
+ FragSizeInvalidExecutionModel,
+ ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+ Combine(Values("FragSizeEXT"), Values("Vertex"), Values("Input"),
+ Values("%u32vec2"), Values("OpCapability FragmentDensityEXT\n"),
+ Values("OpExtension \"SPV_EXT_fragment_invocation_density\"\n"),
+ Values("VUID-FragSizeEXT-FragSizeEXT-04220"),
+ Values(TestResult(SPV_ERROR_INVALID_DATA,
+ "Vulkan spec allows BuiltIn FragSizeEXT to be "
+ "used only with Fragment execution model."))));
+
+INSTANTIATE_TEST_SUITE_P(
+ FragSizeInvalidStorageClass,
+ ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+ Combine(
+ Values("FragSizeEXT"), Values("Fragment"), Values("Output"),
+ Values("%u32vec2"), Values("OpCapability FragmentDensityEXT\n"),
+ Values("OpExtension \"SPV_EXT_fragment_invocation_density\"\n"),
+ Values("VUID-FragSizeEXT-FragSizeEXT-04221"),
+ Values(TestResult(SPV_ERROR_INVALID_DATA,
+ "Vulkan spec allows BuiltIn FragSizeEXT to be only "
+ "used for variables with Input storage class."))));
+
+INSTANTIATE_TEST_SUITE_P(
+ FragSizeInvalidType,
+ ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+ Combine(Values("FragSizeEXT"), Values("Fragment"), Values("Input"),
+ Values("%u32vec3"), Values("OpCapability FragmentDensityEXT\n"),
+ Values("OpExtension \"SPV_EXT_fragment_invocation_density\"\n"),
+ Values("VUID-FragSizeEXT-FragSizeEXT-04222"),
+ Values(TestResult(
+ SPV_ERROR_INVALID_DATA,
+ "According to the Vulkan spec BuiltIn FragSizeEXT variable "
+ "needs to be a 2-component 32-bit int vector."))));
+
+INSTANTIATE_TEST_SUITE_P(
+ FragStencilRefOutputSuccess,
+ ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+ Combine(Values("FragStencilRefEXT"), Values("Fragment"), Values("Output"),
+ Values("%u32", "%u64"), Values("OpCapability StencilExportEXT\n"),
+ Values("OpExtension \"SPV_EXT_shader_stencil_export\"\n"),
+ Values(nullptr), Values(TestResult())));
+
+INSTANTIATE_TEST_SUITE_P(
+ FragStencilRefInvalidExecutionModel,
+ ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+ Combine(Values("FragStencilRefEXT"), Values("Vertex"), Values("Output"),
+ Values("%u32", "%u64"), Values("OpCapability StencilExportEXT\n"),
+ Values("OpExtension \"SPV_EXT_shader_stencil_export\"\n"),
+ Values("VUID-FragStencilRefEXT-FragStencilRefEXT-04223"),
+ Values(TestResult(SPV_ERROR_INVALID_DATA,
+ "Vulkan spec allows BuiltIn FragStencilRefEXT to "
+ "be used only with Fragment execution model."))));
+
+INSTANTIATE_TEST_SUITE_P(
+ FragStencilRefInvalidStorageClass,
+ ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+ Combine(Values("FragStencilRefEXT"), Values("Fragment"), Values("Input"),
+ Values("%u32", "%u64"), Values("OpCapability StencilExportEXT\n"),
+ Values("OpExtension \"SPV_EXT_shader_stencil_export\"\n"),
+ Values("VUID-FragStencilRefEXT-FragStencilRefEXT-04224"),
+ Values(TestResult(
+ SPV_ERROR_INVALID_DATA,
+ "Vulkan spec allows BuiltIn FragStencilRefEXT to be only used "
+ "for variables with Output storage class."))));
+
+INSTANTIATE_TEST_SUITE_P(
+ FragStencilRefInvalidType,
+ ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+ Combine(Values("FragStencilRefEXT"), Values("Fragment"), Values("Output"),
+ Values("%f32", "%f64", "%u32vec2"),
+ Values("OpCapability StencilExportEXT\n"),
+ Values("OpExtension \"SPV_EXT_shader_stencil_export\"\n"),
+ Values("VUID-FragStencilRefEXT-FragStencilRefEXT-04225"),
+ Values(TestResult(
+ SPV_ERROR_INVALID_DATA,
+ "According to the Vulkan spec BuiltIn FragStencilRefEXT "
+ "variable needs to be a int scalar."))));
+
+INSTANTIATE_TEST_SUITE_P(
+ FullyCoveredEXTInputSuccess,
+ ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+ Combine(Values("FullyCoveredEXT"), Values("Fragment"), Values("Input"),
+ Values("%bool"), Values("OpCapability FragmentFullyCoveredEXT\n"),
+ Values("OpExtension \"SPV_EXT_fragment_fully_covered\"\n"),
+ Values(nullptr), Values(TestResult())));
+
+INSTANTIATE_TEST_SUITE_P(
+ FullyCoveredEXTInvalidExecutionModel,
+ ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+ Combine(Values("FullyCoveredEXT"), Values("Vertex"), Values("Input"),
+ Values("%bool"), Values("OpCapability FragmentFullyCoveredEXT\n"),
+ Values("OpExtension \"SPV_EXT_fragment_fully_covered\"\n"),
+ Values("VUID-FullyCoveredEXT-FullyCoveredEXT-04232"),
+ Values(TestResult(SPV_ERROR_INVALID_DATA,
+ "Vulkan spec allows BuiltIn FullyCoveredEXT to "
+ "be used only with Fragment execution model."))));
+
+INSTANTIATE_TEST_SUITE_P(
+ FullyCoveredEXTInvalidStorageClass,
+ ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+ Combine(Values("FullyCoveredEXT"), Values("Fragment"), Values("Output"),
+ Values("%bool"), Values("OpCapability FragmentFullyCoveredEXT\n"),
+ Values("OpExtension \"SPV_EXT_fragment_fully_covered\"\n"),
+ Values("VUID-FullyCoveredEXT-FullyCoveredEXT-04233"),
+ Values(TestResult(
+ SPV_ERROR_INVALID_DATA,
+ "Vulkan spec allows BuiltIn FullyCoveredEXT to be only used "
+ "for variables with Input storage class."))));
+
+INSTANTIATE_TEST_SUITE_P(
+ FullyCoveredEXTInvalidType,
+ ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
+ Combine(Values("FullyCoveredEXT"), Values("Fragment"), Values("Input"),
+ Values("%f32"), Values("OpCapability FragmentFullyCoveredEXT\n"),
+ Values("OpExtension \"SPV_EXT_fragment_fully_covered\"\n"),
+ Values("VUID-FullyCoveredEXT-FullyCoveredEXT-04234"),
+ Values(TestResult(
+ SPV_ERROR_INVALID_DATA,
+ "According to the Vulkan spec BuiltIn FullyCoveredEXT variable "
+ "needs to be a bool scalar."))));
+
} // namespace
} // namespace val
} // namespace spvtools