Fix Component decoration validation for arrays (#2697)
diff --git a/source/val/validate_decorations.cpp b/source/val/validate_decorations.cpp
index 5174600..14cc820 100644
--- a/source/val/validate_decorations.cpp
+++ b/source/val/validate_decorations.cpp
@@ -1440,6 +1440,11 @@
}
if (spvIsVulkanEnv(vstate.context()->target_env)) {
+ // Strip the array, if present.
+ if (vstate.GetIdOpcode(type_id) == SpvOpTypeArray) {
+ type_id = vstate.FindDef(type_id)->word(2u);
+ }
+
if (!vstate.IsIntScalarOrVectorType(type_id) &&
!vstate.IsFloatScalarOrVectorType(type_id)) {
return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
diff --git a/test/val/val_decoration_test.cpp b/test/val/val_decoration_test.cpp
index 5ea1d87..9ecb382 100644
--- a/test/val/val_decoration_test.cpp
+++ b/test/val/val_decoration_test.cpp
@@ -6491,10 +6491,14 @@
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
-%vtype = )" + type + R"(
+%v3float = OpTypeVector %float 3
+%v4float = OpTypeVector %float 4
+%uint = OpTypeInt 32 0
+%uint_2 = OpConstant %uint 2
+%arr_v3float_uint_2 = OpTypeArray %v3float %uint_2
%float_0 = OpConstant %float 0
-%_ptr_Output_vtype = OpTypePointer Output %vtype
-%entryPointOutput = OpVariable %_ptr_Output_vtype Output
+%_ptr_Output_type = OpTypePointer Output %)" + type + R"(
+%entryPointOutput = OpVariable %_ptr_Output_type Output
%main = OpFunction %void None %3
%5 = OpLabel
OpReturn
@@ -6504,8 +6508,7 @@
TEST_F(ValidateDecorations, ComponentDecorationIntGood0Vulkan) {
const spv_target_env env = SPV_ENV_VULKAN_1_0;
- std::string spirv =
- ShaderWithComponentDecoration("OpTypeInt 32 0", "Component 0");
+ std::string spirv = ShaderWithComponentDecoration("uint", "Component 0");
CompileSuccessfully(spirv, env);
EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
@@ -6514,8 +6517,7 @@
TEST_F(ValidateDecorations, ComponentDecorationIntGood1Vulkan) {
const spv_target_env env = SPV_ENV_VULKAN_1_0;
- std::string spirv =
- ShaderWithComponentDecoration("OpTypeInt 32 0", "Component 1");
+ std::string spirv = ShaderWithComponentDecoration("uint", "Component 1");
CompileSuccessfully(spirv, env);
EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
@@ -6524,8 +6526,7 @@
TEST_F(ValidateDecorations, ComponentDecorationIntGood2Vulkan) {
const spv_target_env env = SPV_ENV_VULKAN_1_0;
- std::string spirv =
- ShaderWithComponentDecoration("OpTypeInt 32 0", "Component 2");
+ std::string spirv = ShaderWithComponentDecoration("uint", "Component 2");
CompileSuccessfully(spirv, env);
EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
@@ -6534,8 +6535,7 @@
TEST_F(ValidateDecorations, ComponentDecorationIntGood3Vulkan) {
const spv_target_env env = SPV_ENV_VULKAN_1_0;
- std::string spirv =
- ShaderWithComponentDecoration("OpTypeInt 32 0", "Component 3");
+ std::string spirv = ShaderWithComponentDecoration("uint", "Component 3");
CompileSuccessfully(spirv, env);
EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
@@ -6544,8 +6544,7 @@
TEST_F(ValidateDecorations, ComponentDecorationIntBad4Vulkan) {
const spv_target_env env = SPV_ENV_VULKAN_1_0;
- std::string spirv =
- ShaderWithComponentDecoration("OpTypeInt 32 0", "Component 4");
+ std::string spirv = ShaderWithComponentDecoration("uint", "Component 4");
CompileSuccessfully(spirv, env);
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
@@ -6556,8 +6555,7 @@
TEST_F(ValidateDecorations, ComponentDecorationVector3GoodVulkan) {
const spv_target_env env = SPV_ENV_VULKAN_1_0;
- std::string spirv =
- ShaderWithComponentDecoration("OpTypeVector %float 3", "Component 1");
+ std::string spirv = ShaderWithComponentDecoration("v3float", "Component 1");
CompileSuccessfully(spirv, env);
EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
@@ -6566,8 +6564,7 @@
TEST_F(ValidateDecorations, ComponentDecorationVector4GoodVulkan) {
const spv_target_env env = SPV_ENV_VULKAN_1_0;
- std::string spirv =
- ShaderWithComponentDecoration("OpTypeVector %float 4", "Component 0");
+ std::string spirv = ShaderWithComponentDecoration("v4float", "Component 0");
CompileSuccessfully(spirv, env);
EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
@@ -6576,8 +6573,7 @@
TEST_F(ValidateDecorations, ComponentDecorationVector4Bad1Vulkan) {
const spv_target_env env = SPV_ENV_VULKAN_1_0;
- std::string spirv =
- ShaderWithComponentDecoration("OpTypeVector %float 4", "Component 1");
+ std::string spirv = ShaderWithComponentDecoration("v4float", "Component 1");
CompileSuccessfully(spirv, env);
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
@@ -6588,8 +6584,7 @@
TEST_F(ValidateDecorations, ComponentDecorationVector4Bad3Vulkan) {
const spv_target_env env = SPV_ENV_VULKAN_1_0;
- std::string spirv =
- ShaderWithComponentDecoration("OpTypeVector %float 4", "Component 3");
+ std::string spirv = ShaderWithComponentDecoration("v4float", "Component 3");
CompileSuccessfully(spirv, env);
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
@@ -6598,6 +6593,28 @@
"and ending with 6 gets larger than 3"));
}
+TEST_F(ValidateDecorations, ComponentDecorationArrayGoodVulkan) {
+ const spv_target_env env = SPV_ENV_VULKAN_1_0;
+ std::string spirv =
+ ShaderWithComponentDecoration("arr_v3float_uint_2", "Component 1");
+
+ CompileSuccessfully(spirv, env);
+ EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
+ EXPECT_THAT(getDiagnosticString(), Eq(""));
+}
+
+TEST_F(ValidateDecorations, ComponentDecorationArrayBadVulkan) {
+ const spv_target_env env = SPV_ENV_VULKAN_1_0;
+ std::string spirv =
+ ShaderWithComponentDecoration("arr_v3float_uint_2", "Component 2");
+
+ CompileSuccessfully(spirv, env);
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Sequence of components starting with 2 "
+ "and ending with 4 gets larger than 3"));
+}
+
TEST_F(ValidateDecorations, ComponentDecorationBlockGood) {
std::string spirv = R"(
OpCapability Shader