Skip to content

Commit 20ad38c

Browse files
spirv-val: Multiple interface var with same SC (KhronosGroup#5528)
1 parent e08c012 commit 20ad38c

File tree

4 files changed

+200
-0
lines changed

4 files changed

+200
-0
lines changed

source/val/validate_interfaces.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,64 @@ spv_result_t ValidateLocations(ValidationState_t& _,
587587
return SPV_SUCCESS;
588588
}
589589

590+
spv_result_t ValidateStorageClass(ValidationState_t& _,
591+
const Instruction* entry_point) {
592+
bool has_push_constant = false;
593+
bool has_ray_payload = false;
594+
bool has_hit_attribute = false;
595+
bool has_callable_data = false;
596+
for (uint32_t i = 3; i < entry_point->operands().size(); ++i) {
597+
auto interface_id = entry_point->GetOperandAs<uint32_t>(i);
598+
auto interface_var = _.FindDef(interface_id);
599+
auto storage_class = interface_var->GetOperandAs<spv::StorageClass>(2);
600+
switch (storage_class) {
601+
case spv::StorageClass::PushConstant: {
602+
if (has_push_constant) {
603+
return _.diag(SPV_ERROR_INVALID_DATA, entry_point)
604+
<< _.VkErrorID(6673)
605+
<< "Entry-point has more than one variable with the "
606+
"PushConstant storage class in the interface";
607+
}
608+
has_push_constant = true;
609+
break;
610+
}
611+
case spv::StorageClass::IncomingRayPayloadKHR: {
612+
if (has_ray_payload) {
613+
return _.diag(SPV_ERROR_INVALID_DATA, entry_point)
614+
<< _.VkErrorID(4700)
615+
<< "Entry-point has more than one variable with the "
616+
"IncomingRayPayloadKHR storage class in the interface";
617+
}
618+
has_ray_payload = true;
619+
break;
620+
}
621+
case spv::StorageClass::HitAttributeKHR: {
622+
if (has_hit_attribute) {
623+
return _.diag(SPV_ERROR_INVALID_DATA, entry_point)
624+
<< _.VkErrorID(4702)
625+
<< "Entry-point has more than one variable with the "
626+
"HitAttributeKHR storage class in the interface";
627+
}
628+
has_hit_attribute = true;
629+
break;
630+
}
631+
case spv::StorageClass::IncomingCallableDataKHR: {
632+
if (has_callable_data) {
633+
return _.diag(SPV_ERROR_INVALID_DATA, entry_point)
634+
<< _.VkErrorID(4706)
635+
<< "Entry-point has more than one variable with the "
636+
"IncomingCallableDataKHR storage class in the interface";
637+
}
638+
has_callable_data = true;
639+
break;
640+
}
641+
default:
642+
break;
643+
}
644+
}
645+
return SPV_SUCCESS;
646+
}
647+
590648
} // namespace
591649

592650
spv_result_t ValidateInterfaces(ValidationState_t& _) {
@@ -605,6 +663,9 @@ spv_result_t ValidateInterfaces(ValidationState_t& _) {
605663
if (auto error = ValidateLocations(_, &inst)) {
606664
return error;
607665
}
666+
if (auto error = ValidateStorageClass(_, &inst)) {
667+
return error;
668+
}
608669
}
609670
if (inst.opcode() == spv::Op::OpTypeVoid) break;
610671
}

source/val/validation_state.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2173,14 +2173,20 @@ std::string ValidationState_t::VkErrorID(uint32_t id,
21732173
return VUID_WRAP(VUID-StandaloneSpirv-RayPayloadKHR-04698);
21742174
case 4699:
21752175
return VUID_WRAP(VUID-StandaloneSpirv-IncomingRayPayloadKHR-04699);
2176+
case 4700:
2177+
return VUID_WRAP(VUID-StandaloneSpirv-IncomingRayPayloadKHR-04700);
21762178
case 4701:
21772179
return VUID_WRAP(VUID-StandaloneSpirv-HitAttributeKHR-04701);
2180+
case 4702:
2181+
return VUID_WRAP(VUID-StandaloneSpirv-HitAttributeKHR-04702);
21782182
case 4703:
21792183
return VUID_WRAP(VUID-StandaloneSpirv-HitAttributeKHR-04703);
21802184
case 4704:
21812185
return VUID_WRAP(VUID-StandaloneSpirv-CallableDataKHR-04704);
21822186
case 4705:
21832187
return VUID_WRAP(VUID-StandaloneSpirv-IncomingCallableDataKHR-04705);
2188+
case 4706:
2189+
return VUID_WRAP(VUID-StandaloneSpirv-IncomingCallableDataKHR-04706);
21842190
case 7119:
21852191
return VUID_WRAP(VUID-StandaloneSpirv-ShaderRecordBufferKHR-07119);
21862192
case 4708:
@@ -2239,6 +2245,8 @@ std::string ValidationState_t::VkErrorID(uint32_t id,
22392245
return VUID_WRAP(VUID-StandaloneSpirv-OpTypeSampledImage-06671);
22402246
case 6672:
22412247
return VUID_WRAP(VUID-StandaloneSpirv-Location-06672);
2248+
case 6673:
2249+
return VUID_WRAP(VUID-StandaloneSpirv-OpVariable-06673);
22422250
case 6674:
22432251
return VUID_WRAP(VUID-StandaloneSpirv-OpEntryPoint-06674);
22442252
case 6675:

test/val/val_decoration_test.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3209,6 +3209,48 @@ TEST_F(ValidateDecorations,
32093209
"statically used per shader entry point."));
32103210
}
32113211

3212+
TEST_F(ValidateDecorations,
3213+
VulkanMultiplePushConstantsSingleEntryPointInterfaceBad) {
3214+
std::string spirv = R"(
3215+
OpCapability Shader
3216+
OpMemoryModel Logical GLSL450
3217+
OpEntryPoint Vertex %func1 "func1" %pc1 %pc2
3218+
OpDecorate %struct Block
3219+
OpMemberDecorate %struct 0 Offset 0
3220+
%void = OpTypeVoid
3221+
%voidfn = OpTypeFunction %void
3222+
%float = OpTypeFloat 32
3223+
%int = OpTypeInt 32 0
3224+
%int_0 = OpConstant %int 0
3225+
%struct = OpTypeStruct %float
3226+
%ptr = OpTypePointer PushConstant %struct
3227+
%ptr_float = OpTypePointer PushConstant %float
3228+
%pc1 = OpVariable %ptr PushConstant
3229+
%pc2 = OpVariable %ptr PushConstant
3230+
%func1 = OpFunction %void None %voidfn
3231+
%label1 = OpLabel
3232+
%access1 = OpAccessChain %ptr_float %pc1 %int_0
3233+
%load1 = OpLoad %float %access1
3234+
OpReturn
3235+
OpFunctionEnd
3236+
%func2 = OpFunction %void None %voidfn
3237+
%label2 = OpLabel
3238+
%access2 = OpAccessChain %ptr_float %pc2 %int_0
3239+
%load2 = OpLoad %float %access2
3240+
OpReturn
3241+
OpFunctionEnd
3242+
)";
3243+
3244+
CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
3245+
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
3246+
ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_2));
3247+
EXPECT_THAT(getDiagnosticString(),
3248+
AnyVUID("VUID-StandaloneSpirv-OpVariable-06673"));
3249+
EXPECT_THAT(getDiagnosticString(),
3250+
HasSubstr("Entry-point has more than one variable with the "
3251+
"PushConstant storage class in the interface"));
3252+
}
3253+
32123254
TEST_F(ValidateDecorations, VulkanUniformMissingDescriptorSetBad) {
32133255
std::string spirv = R"(
32143256
OpCapability Shader

test/val/val_ray_tracing_test.cpp

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,95 @@ OpTraceRayKHR %as %uint_1 %uint_1 %uint_1 %uint_1 %uint_1 %v3composite %float_0
578578
"IncomingRayPayloadKHR"));
579579
}
580580

581+
TEST_F(ValidateRayTracing, InterfaceIncomingRayPayload) {
582+
const std::string body = R"(
583+
OpCapability RayTracingKHR
584+
OpExtension "SPV_KHR_ray_tracing"
585+
OpMemoryModel Logical GLSL450
586+
OpEntryPoint CallableKHR %main "main" %inData1 %inData2
587+
OpName %main "main"
588+
%void = OpTypeVoid
589+
%func = OpTypeFunction %void
590+
%int = OpTypeInt 32 1
591+
%inData_ptr = OpTypePointer IncomingRayPayloadKHR %int
592+
%inData1 = OpVariable %inData_ptr IncomingRayPayloadKHR
593+
%inData2 = OpVariable %inData_ptr IncomingRayPayloadKHR
594+
%main = OpFunction %void None %func
595+
%label = OpLabel
596+
OpReturn
597+
OpFunctionEnd
598+
)";
599+
600+
CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
601+
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
602+
ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_2));
603+
EXPECT_THAT(getDiagnosticString(),
604+
AnyVUID("VUID-StandaloneSpirv-IncomingRayPayloadKHR-04700"));
605+
EXPECT_THAT(
606+
getDiagnosticString(),
607+
HasSubstr("Entry-point has more than one variable with the "
608+
"IncomingRayPayloadKHR storage class in the interface"));
609+
}
610+
611+
TEST_F(ValidateRayTracing, InterfaceHitAttribute) {
612+
const std::string body = R"(
613+
OpCapability RayTracingKHR
614+
OpExtension "SPV_KHR_ray_tracing"
615+
OpMemoryModel Logical GLSL450
616+
OpEntryPoint CallableKHR %main "main" %inData1 %inData2
617+
OpName %main "main"
618+
%void = OpTypeVoid
619+
%func = OpTypeFunction %void
620+
%int = OpTypeInt 32 1
621+
%inData_ptr = OpTypePointer HitAttributeKHR %int
622+
%inData1 = OpVariable %inData_ptr HitAttributeKHR
623+
%inData2 = OpVariable %inData_ptr HitAttributeKHR
624+
%main = OpFunction %void None %func
625+
%label = OpLabel
626+
OpReturn
627+
OpFunctionEnd
628+
)";
629+
630+
CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
631+
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
632+
ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_2));
633+
EXPECT_THAT(getDiagnosticString(),
634+
AnyVUID("VUID-StandaloneSpirv-HitAttributeKHR-04702"));
635+
EXPECT_THAT(getDiagnosticString(),
636+
HasSubstr("Entry-point has more than one variable with the "
637+
"HitAttributeKHR storage class in the interface"));
638+
}
639+
640+
TEST_F(ValidateRayTracing, InterfaceIncomingCallableData) {
641+
const std::string body = R"(
642+
OpCapability RayTracingKHR
643+
OpExtension "SPV_KHR_ray_tracing"
644+
OpMemoryModel Logical GLSL450
645+
OpEntryPoint CallableKHR %main "main" %inData1 %inData2
646+
OpName %main "main"
647+
%void = OpTypeVoid
648+
%func = OpTypeFunction %void
649+
%int = OpTypeInt 32 1
650+
%inData_ptr = OpTypePointer IncomingCallableDataKHR %int
651+
%inData1 = OpVariable %inData_ptr IncomingCallableDataKHR
652+
%inData2 = OpVariable %inData_ptr IncomingCallableDataKHR
653+
%main = OpFunction %void None %func
654+
%label = OpLabel
655+
OpReturn
656+
OpFunctionEnd
657+
)";
658+
659+
CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
660+
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
661+
ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_2));
662+
EXPECT_THAT(getDiagnosticString(),
663+
AnyVUID("VUID-StandaloneSpirv-IncomingCallableDataKHR-04706"));
664+
EXPECT_THAT(
665+
getDiagnosticString(),
666+
HasSubstr("Entry-point has more than one variable with the "
667+
"IncomingCallableDataKHR storage class in the interface"));
668+
}
669+
581670
} // namespace
582671
} // namespace val
583672
} // namespace spvtools

0 commit comments

Comments
 (0)