mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-26 21:30:07 +00:00
spirv-val: Add Vulkan Invariant Decoration VUID (#4132)
This commit is contained in:
parent
c91a25af13
commit
f11f743481
@ -407,6 +407,10 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) {
|
||||
<< "' is not a pointer type.";
|
||||
}
|
||||
|
||||
const auto type_index = 2;
|
||||
const auto value_id = result_type->GetOperandAs<uint32_t>(type_index);
|
||||
auto value_type = _.FindDef(value_id);
|
||||
|
||||
const auto initializer_index = 3;
|
||||
const auto storage_class_index = 2;
|
||||
if (initializer_index < inst->operands().size()) {
|
||||
@ -423,7 +427,7 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) {
|
||||
<< "OpVariable Initializer <id> '" << _.getIdName(initializer_id)
|
||||
<< "' is not a constant or module-scope variable.";
|
||||
}
|
||||
if (initializer->type_id() != result_type->GetOperandAs<uint32_t>(2u)) {
|
||||
if (initializer->type_id() != value_id) {
|
||||
return _.diag(SPV_ERROR_INVALID_ID, inst)
|
||||
<< "Initializer type must match the type pointed to by the Result "
|
||||
"Type";
|
||||
@ -440,9 +444,6 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) {
|
||||
storage_class != SpvStorageClassHitAttributeNV &&
|
||||
storage_class != SpvStorageClassCallableDataNV &&
|
||||
storage_class != SpvStorageClassIncomingCallableDataNV) {
|
||||
const auto storage_index = 2;
|
||||
const auto storage_id = result_type->GetOperandAs<uint32_t>(storage_index);
|
||||
const auto storage = _.FindDef(storage_id);
|
||||
bool storage_input_or_output = storage_class == SpvStorageClassInput ||
|
||||
storage_class == SpvStorageClassOutput;
|
||||
bool builtin = false;
|
||||
@ -455,7 +456,7 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) {
|
||||
}
|
||||
}
|
||||
if (!(storage_input_or_output && builtin) &&
|
||||
ContainsInvalidBool(_, storage, storage_input_or_output)) {
|
||||
ContainsInvalidBool(_, value_type, storage_input_or_output)) {
|
||||
return _.diag(SPV_ERROR_INVALID_ID, inst)
|
||||
<< "If OpTypeBool is stored in conjunction with OpVariable, it "
|
||||
<< "can only be used with non-externally visible shader Storage "
|
||||
@ -576,6 +577,28 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) {
|
||||
"of this type";
|
||||
}
|
||||
}
|
||||
|
||||
// Check for invalid use of Invariant
|
||||
if (storage_class != SpvStorageClassInput &&
|
||||
storage_class != SpvStorageClassOutput) {
|
||||
if (_.HasDecoration(inst->id(), SpvDecorationInvariant)) {
|
||||
return _.diag(SPV_ERROR_INVALID_ID, inst)
|
||||
<< _.VkErrorID(4677)
|
||||
<< "Variable decorated with Invariant must only be identified "
|
||||
"with the Input or Output storage class in Vulkan "
|
||||
"environment.";
|
||||
}
|
||||
// Need to check if only the members in a struct are decorated
|
||||
if (value_type && value_type->opcode() == SpvOpTypeStruct) {
|
||||
if (_.HasDecoration(value_id, SpvDecorationInvariant)) {
|
||||
return _.diag(SPV_ERROR_INVALID_ID, inst)
|
||||
<< _.VkErrorID(4677)
|
||||
<< "Variable struct member decorated with Invariant must only "
|
||||
"be identified with the Input or Output storage class in "
|
||||
"Vulkan environment.";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Vulkan Appendix A: Check that if contains initializer, then
|
||||
@ -640,9 +663,6 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) {
|
||||
}
|
||||
|
||||
// Vulkan specific validation rules for OpTypeRuntimeArray
|
||||
const auto type_index = 2;
|
||||
const auto value_id = result_type->GetOperandAs<uint32_t>(type_index);
|
||||
auto value_type = _.FindDef(value_id);
|
||||
if (spvIsVulkanEnv(_.context()->target_env)) {
|
||||
// OpTypeRuntimeArray should only ever be in a container like OpTypeStruct,
|
||||
// so should never appear as a bare variable.
|
||||
|
@ -1710,6 +1710,8 @@ std::string ValidationState_t::VkErrorID(uint32_t id,
|
||||
return VUID_WRAP(VUID-StandaloneSpirv-GLSLShared-04669);
|
||||
case 4675:
|
||||
return VUID_WRAP(VUID-StandaloneSpirv-FPRoundingMode-04675);
|
||||
case 4677:
|
||||
return VUID_WRAP(VUID-StandaloneSpirv-Invariant-04677);
|
||||
case 4683:
|
||||
return VUID_WRAP(VUID-StandaloneSpirv-LocalSize-04683);
|
||||
case 4685:
|
||||
|
@ -4042,6 +4042,109 @@ OpFunctionEnd
|
||||
"typed as OpTypeStruct, or an array of this type"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMemory, VulkanInvariantOutputSuccess) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Vertex %main "main"
|
||||
OpDecorate %var Location 0
|
||||
OpDecorate %var Invariant
|
||||
%void = OpTypeVoid
|
||||
%f32 = OpTypeFloat 32
|
||||
%ptr_output = OpTypePointer Output %f32
|
||||
%var = OpVariable %ptr_output Output
|
||||
%void_fn = OpTypeFunction %void
|
||||
%main = OpFunction %void None %void_fn
|
||||
%entry = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMemory, VulkanInvariantInputStructSuccess) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpDecorate %var Location 0
|
||||
OpMemberDecorate %struct 1 Invariant
|
||||
%void = OpTypeVoid
|
||||
%f32 = OpTypeFloat 32
|
||||
%struct = OpTypeStruct %f32 %f32
|
||||
%ptr_input = OpTypePointer Input %struct
|
||||
%var = OpVariable %ptr_input Input
|
||||
%void_fn = OpTypeFunction %void
|
||||
%main = OpFunction %void None %void_fn
|
||||
%entry = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMemory, VulkanInvariantWrongStorageClass) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Vertex %main "main"
|
||||
OpDecorate %var Invariant
|
||||
%void = OpTypeVoid
|
||||
%f32 = OpTypeFloat 32
|
||||
%ptr_private = OpTypePointer Private %f32
|
||||
%var = OpVariable %ptr_private Private
|
||||
%void_fn = OpTypeFunction %void
|
||||
%main = OpFunction %void None %void_fn
|
||||
%entry = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
AnyVUID("VUID-StandaloneSpirv-Invariant-04677"));
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr(
|
||||
"Variable decorated with Invariant must only be identified with the "
|
||||
"Input or Output storage class in Vulkan environment."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMemory, VulkanInvariantMemberWrongStorageClass) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpMemberDecorate %struct 1 Invariant
|
||||
%void = OpTypeVoid
|
||||
%f32 = OpTypeFloat 32
|
||||
%struct = OpTypeStruct %f32 %f32
|
||||
%ptr_private = OpTypePointer Private %struct
|
||||
%var = OpVariable %ptr_private Private
|
||||
%void_fn = OpTypeFunction %void
|
||||
%main = OpFunction %void None %void_fn
|
||||
%entry = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
AnyVUID("VUID-StandaloneSpirv-Invariant-04677"));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("Variable struct member decorated with Invariant must "
|
||||
"only be identified with the Input or Output storage "
|
||||
"class in Vulkan environment."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateMemory, PhysicalStorageBufferPtrEqual) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
|
Loading…
Reference in New Issue
Block a user