From c656c23ad3873926bfd84058c1f80fda5743901e Mon Sep 17 00:00:00 2001 From: Ehsan Nasiri Date: Tue, 3 Jan 2017 14:53:50 -0500 Subject: [PATCH] Refactoring unit tests using TEST_P. Using parameterized unit tests to avoid duplicate code that runs the tests of OpAccessChain and OpInBoundsAccessChain. This is also a steppingstone to adding tests for OpPtrAccessChain and OpInBoundsPtrAccessChain. --- test/val/val_id_test.cpp | 610 ++++++++++++++--------------------------------- 1 file changed, 179 insertions(+), 431 deletions(-) diff --git a/test/val/val_id_test.cpp b/test/val/val_id_test.cpp index 21ba26b..203b81d 100644 --- a/test/val/val_id_test.cpp +++ b/test/val/val_id_test.cpp @@ -1890,415 +1890,130 @@ string opAccessChainSpirvSetup = R"( %my_label = OpLabel )"; -// Valid: Access a float in a matrix using OpAccessChain -TEST_F(ValidateIdWithMessage, OpAccessChainGood) { - string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%float_entry = OpAccessChain %_ptr_Private_float %my_matrix %int_0 %int_1 -OpReturn -OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Invalid. The result type of OpAccessChain must be a pointer. -TEST_F(ValidateIdWithMessage, OpAccessChainResultTypeBad) { - string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%float_entry = OpAccessChain %float %my_matrix %int_0 %int_1 -OpReturn -OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("The Result Type of OpAccessChain '36' must be " - "OpTypePointer. Found OpTypeFloat.")); -} - -// Invalid. The base type of OpAccessChain must be a pointer. -TEST_F(ValidateIdWithMessage, OpAccessChainBaseTypeVoidBad) { - string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%float_entry = OpAccessChain %_ptr_Private_float %void %int_0 %int_1 -OpReturn -OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("The Base '1' in OpAccessChain instruction must " - "be a pointer.")); -} - -// Invalid. The base type of OpAccessChain must be a pointer. -TEST_F(ValidateIdWithMessage, OpAccessChainBaseTypeNonPtrVariableBad) { - string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%entry = OpAccessChain %_ptr_Private_float %_ptr_Private_float %int_0 %int_1 -OpReturn -OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("The Base '8' in OpAccessChain instruction must " - "be a pointer.")); -} - -// Invalid: The storage class of Base and Result do not match. -TEST_F(ValidateIdWithMessage, - OpAccessChainResultAndBaseStorageClassDoesntMatchBad) { - string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%entry = OpAccessChain %_ptr_Function_float %my_matrix %int_0 %int_1 -OpReturn -OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("The result pointer storage class and base pointer " - "storage class in OpAccessChain do not match.")); -} - -// Invalid. The base type of OpAccessChain must point to a composite object. -TEST_F(ValidateIdWithMessage, OpAccessChainBasePtrNotPointingToCompositeBad) { - string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%entry = OpAccessChain %_ptr_Private_float %my_float_var %int_0 -OpReturn -OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpAccessChain reached non-composite type while " - "indexes still remain to be traversed.")); -} - -// Invalid. No Indexes passed to OpAccessChain -TEST_F(ValidateIdWithMessage, OpAccessChainMissingIndexesBad) { - string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%entry = OpAccessChain %_ptr_Private_float %my_float_var -OpReturn -OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("No Indexes were passes to OpAccessChain.")); -} - -// Valid: 255 indexes passed to OpAccessChain. Limit is 255. -TEST_F(ValidateIdWithMessage, OpAccessChainTooManyIndexesGood) { - int depth = 255; - std::string header = kGLSL450MemoryModel + opAccessChainSpirvSetup; - header.erase(header.find("%func")); - std::ostringstream spirv; - spirv << header << "\n"; - - // Build nested structures. Struct 'i' contains struct 'i-1' - spirv << "%s_depth_1 = OpTypeStruct %float\n"; - for (int i = 2; i <= depth; ++i) { - spirv << "%s_depth_" << i << " = OpTypeStruct %s_depth_" << i - 1 << "\n"; - } - - // Define Pointer and Variable to use for OpAccessChain. - spirv << "%_ptr_Uniform_deep_struct = OpTypePointer Uniform %s_depth_" - << depth << "\n"; - spirv << "%deep_var = OpVariable %_ptr_Uniform_deep_struct Uniform\n"; - - // Function Start - spirv << R"( - %func = OpFunction %void None %void_f - %my_label = OpLabel - )"; - - // OpAccessChain with 'n' indexes (n = depth) - spirv << "%entry = OpAccessChain %_ptr_Uniform_float %deep_var"; - for (int i = 0; i < depth; ++i) { - spirv << " %int_0"; - } - - // Function end - spirv << R"( - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Invalid: 256 indexes passed to OpAccessChain. Limit is 255. -TEST_F(ValidateIdWithMessage, OpAccessChainTooManyIndexesBad) { - std::ostringstream spirv; - spirv << kGLSL450MemoryModel << opAccessChainSpirvSetup; - spirv << "%entry = OpAccessChain %_ptr_Private_float %my_matrix"; - for (int i = 0; i < 256; ++i) { - spirv << " %int_0"; - } - spirv << R"( - OpReturn - OpFunctionEnd - )"; - CompileSuccessfully(spirv.str()); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("The number of indexes in OpAccessChain may not exceed " - "255. Found 256 indexes.")); -} - -// Invalid: Index passed to OpAccessChain is float (must be integer). -TEST_F(ValidateIdWithMessage, OpAccessChainUndefinedIndexBad) { - string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%entry = OpAccessChain %_ptr_Private_float %my_matrix %float %int_1 -OpReturn -OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Indexes passed to OpAccessChain must be of type integer.")); -} - -// Invalid: The OpAccessChain index argument that indexes into a struct must be -// of type OpConstant. -TEST_F(ValidateIdWithMessage, OpAccessChainStructIndexNotConstantBad) { - string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%f = OpAccessChain %_ptr_Uniform_float %blockName_var %int_0 %spec_int %int_2 -OpReturn -OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("The passed to OpAccessChain to index into a " - "structure must be an OpConstant.")); -} - -// Invalid: Indexing up to a vec4 granularity, but result type expected float. -TEST_F(ValidateIdWithMessage, - OpAccessChainStructResultTypeDoesntMatchIndexedTypeBad) { - string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%entry = OpAccessChain %_ptr_Uniform_float %blockName_var %int_0 %int_1 %int_2 -OpReturn -OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "OpAccessChain result type (OpTypeFloat) does not match the type " - "that results from indexing into the base (OpTypeVector).")); -} - -// Invalid: Reach non-composite type (bool) when unused indexes remain. -TEST_F(ValidateIdWithMessage, OpAccessChainStructTooManyIndexesBad) { - string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%entry = OpAccessChain %_ptr_Uniform_float %blockName_var %int_0 %int_2 %int_2 -OpReturn -OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpAccessChain reached non-composite type while " - "indexes still remain to be traversed.")); -} - -// Invalid: Trying to find index 3 of the struct that has only 3 members. -TEST_F(ValidateIdWithMessage, OpAccessChainStructIndexOutOfBoundBad) { - string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%entry = OpAccessChain %_ptr_Uniform_float %blockName_var %int_3 %int_2 %int_2 -OpReturn -OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Index is out of bound: OpAccessChain can not find " - "index 3 into the structure '26'. This structure " - "has 3 members. Largest valid index is 2.")); -} - -// Valid: Tests that we can index into Struct, Array, Matrix, and Vector! -TEST_F(ValidateIdWithMessage, OpAccessChainIndexIntoAllTypesGood) { - // indexes that we are passing are: 0, 3, 1, 2, 0 - // 0 will select the struct_s within the base struct (blockName) - // 3 will select the Array that contains 5 matrices - // 1 will select the Matrix that is at index 1 of the array - // 2 will select the column (which is a vector) within the matrix at index 2 - // 0 will select the element at the index 0 of the vector. (which is a float). - string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%ss = OpAccessChain %_ptr_Uniform_struct_s %blockName_var %int_0 -%sa = OpAccessChain %_ptr_Uniform_array5_mat4x3 %blockName_var %int_0 %int_3 -%sm = OpAccessChain %_ptr_Uniform_mat4x3 %blockName_var %int_0 %int_3 %int_1 -%sc = OpAccessChain %_ptr_Uniform_v3float %blockName_var %int_0 %int_3 %int_1 %int_2 -%entry = OpAccessChain %_ptr_Uniform_float %blockName_var %int_0 %int_3 %int_1 %int_2 %int_0 -OpReturn -OpFunctionEnd - )"; +// In what follows, Access Chain Instruction refers to one of the following: +// OpAccessChain, OpInBoundsAccessChain, OpPtrAccessChain, and +// OpInBoundsPtrAccessChain +using AccessChainInstructionTest = spvtest::ValidateBase; + +// Valid: Access a float in a matrix using an access chain instruction. +TEST_P(AccessChainInstructionTest, AccessChainGood) { + const std::string instr = GetParam(); + string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + + "%float_entry = " + instr + + R"( %_ptr_Private_float %my_matrix %int_0 %int_1 + OpReturn + OpFunctionEnd + )"; CompileSuccessfully(spirv); EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); } -// Valid: Access an element of OpTypeRuntimeArray. -TEST_F(ValidateIdWithMessage, OpAccessChainIndexIntoRuntimeArrayGood) { +// Invalid. The result type of an access chain instruction must be a pointer. +TEST_P(AccessChainInstructionTest, AccessChainResultTypeBad) { + const std::string instr = GetParam(); string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%runtime_arr_entry = OpAccessChain %_ptr_Uniform_float %blockName_var %int_2 %int_0 +%float_entry = )" + + instr + R"( %float %my_matrix %int_0 %int_1 OpReturn OpFunctionEnd )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} -// Invalid: Unused index when accessing OpTypeRuntimeArray. -TEST_F(ValidateIdWithMessage, OpAccessChainIndexIntoRuntimeArrayBad) { - string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%runtime_arr_entry = OpAccessChain %_ptr_Uniform_float %blockName_var %int_2 %int_0 %int_1 -OpReturn -OpFunctionEnd - )"; + const std::string expected_err = "The Result Type of " + instr + + " '36' must be " + "OpTypePointer. Found OpTypeFloat."; CompileSuccessfully(spirv); EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpAccessChain reached non-composite type while " - "indexes still remain to be traversed.")); + EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err)); } -// Invalid: Reached scalar type before arguments to OpAccessChain finished. -TEST_F(ValidateIdWithMessage, OpAccessChainMatrixMoreArgsThanNeededBad) { +// Invalid. The base type of an access chain instruction must be a pointer. +TEST_P(AccessChainInstructionTest, AccessChainBaseTypeVoidBad) { + const std::string instr = GetParam(); string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%entry = OpAccessChain %_ptr_Private_float %my_matrix %int_0 %int_1 %int_0 +%float_entry = )" + + instr + R"( %_ptr_Private_float %void %int_0 %int_1 OpReturn OpFunctionEnd )"; + const std::string expected_err = "The Base '1' in " + instr + + " instruction must " + "be a pointer."; CompileSuccessfully(spirv); EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpAccessChain reached non-composite type while " - "indexes still remain to be traversed.")); + EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err)); } -// Invalid: The result type and the type indexed into do not match. -TEST_F(ValidateIdWithMessage, - OpAccessChainResultTypeDoesntMatchIndexedTypeBad) { +// Invalid. The base type of an access chain instruction must be a pointer. +TEST_P(AccessChainInstructionTest, AccessChainBaseTypeNonPtrVariableBad) { + const std::string instr = GetParam(); string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%entry = OpAccessChain %_ptr_Private_mat4x3 %my_matrix %int_0 %int_1 +%entry = )" + instr + + R"( %_ptr_Private_float %_ptr_Private_float %int_0 %int_1 OpReturn OpFunctionEnd )"; + const std::string expected_err = "The Base '8' in " + instr + + " instruction must " + "be a pointer."; CompileSuccessfully(spirv); EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpAccessChain result type (OpTypeMatrix) does not " - "match the type that results from indexing into the " - "base (OpTypeFloat).")); -} - -// Valid: Access a float in a matrix using OpInBoundsAccessChain -TEST_F(ValidateIdWithMessage, OpInBoundsAccessChainGood) { - string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%float_entry = OpInBoundsAccessChain %_ptr_Private_float %my_matrix %int_0 %int_1 -OpReturn -OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); -} - -// Invalid. The result type of OpInBoundsAccessChain must be a pointer. -TEST_F(ValidateIdWithMessage, OpInBoundsAccessChainResultTypeBad) { - string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%float_entry = OpInBoundsAccessChain %float %my_matrix %int_0 %int_1 -OpReturn -OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("The Result Type of OpInBoundsAccessChain '36' must be " - "OpTypePointer. Found OpTypeFloat.")); -} - -// Invalid. The base type of OpInBoundsAccessChain must be a pointer. -TEST_F(ValidateIdWithMessage, OpInBoundsAccessChainBaseTypeVoidBad) { - string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%float_entry = OpInBoundsAccessChain %_ptr_Private_float %void %int_0 %int_1 -OpReturn -OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("The Base '1' in OpInBoundsAccessChain instruction must " - "be a pointer.")); -} - -// Invalid. The base type of OpInBoundsAccessChain must be a pointer. -TEST_F(ValidateIdWithMessage, OpInBoundsAccessChainBaseTypeNonPtrVariableBad) { - string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%entry = OpInBoundsAccessChain %_ptr_Private_float %_ptr_Private_float %int_0 %int_1 -OpReturn -OpFunctionEnd - )"; - CompileSuccessfully(spirv); - EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("The Base '8' in OpInBoundsAccessChain instruction must " - "be a pointer.")); + EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err)); } // Invalid: The storage class of Base and Result do not match. -TEST_F(ValidateIdWithMessage, - OpInBoundsAccessChainResultAndBaseStorageClassDoesntMatchBad) { +TEST_P(AccessChainInstructionTest, + AccessChainResultAndBaseStorageClassDoesntMatchBad) { + const std::string instr = GetParam(); string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%entry = OpInBoundsAccessChain %_ptr_Function_float %my_matrix %int_0 %int_1 +%entry = )" + instr + + R"( %_ptr_Function_float %my_matrix %int_0 %int_1 OpReturn OpFunctionEnd )"; + const std::string expected_err = + "The result pointer storage class and base pointer storage class in " + + instr + " do not match."; CompileSuccessfully(spirv); EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("The result pointer storage class and base pointer " - "storage class in OpInBoundsAccessChain do not match.")); + EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err)); } -// Invalid. The base type of OpInBoundsAccessChain must point to a composite -// object. -TEST_F(ValidateIdWithMessage, - OpInBoundsAccessChainBasePtrNotPointingToCompositeBad) { +// Invalid. The base type of an access chain instruction must point to a +// composite object. +TEST_P(AccessChainInstructionTest, + AccessChainBasePtrNotPointingToCompositeBad) { + const std::string instr = GetParam(); string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%entry = OpInBoundsAccessChain %_ptr_Private_float %my_float_var %int_0 +%entry = )" + instr + + R"( %_ptr_Private_float %my_float_var %int_0 OpReturn OpFunctionEnd )"; + const std::string expected_err = instr + + " reached non-composite type while " + "indexes still remain to be traversed."; CompileSuccessfully(spirv); EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpInBoundsAccessChain reached non-composite type while " - "indexes still remain to be traversed.")); + EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err)); } -// Invalid. No Indexes passed to OpInBoundsAccessChain -TEST_F(ValidateIdWithMessage, OpInBoundsAccessChainMissingIndexesBad) { +// Invalid. No Indexes passed to the access chain instruction. +TEST_P(AccessChainInstructionTest, AccessChainMissingIndexesBad) { + const std::string instr = GetParam(); string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%entry = OpInBoundsAccessChain %_ptr_Private_float %my_float_var +%entry = )" + instr + + R"( %_ptr_Private_float %my_float_var OpReturn OpFunctionEnd )"; + const std::string expected_err = "No Indexes were passes to " + instr; CompileSuccessfully(spirv); EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("No Indexes were passes to OpInBoundsAccessChain.")); + EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err)); } -// Valid: 255 indexes passed to OpInBoundsAccessChain. Limit is 255. -TEST_F(ValidateIdWithMessage, OpInBoundsAccessChainTooManyIndexesGood) { +// Valid: 255 indexes passed to the access chain instruction. Limit is 255. +TEST_P(AccessChainInstructionTest, AccessChainTooManyIndexesGood) { int depth = 255; std::string header = kGLSL450MemoryModel + opAccessChainSpirvSetup; header.erase(header.find("%func")); @@ -2311,7 +2026,7 @@ TEST_F(ValidateIdWithMessage, OpInBoundsAccessChainTooManyIndexesGood) { spirv << "%s_depth_" << i << " = OpTypeStruct %s_depth_" << i - 1 << "\n"; } - // Define Pointer and Variable to use for OpInBoundsAccessChain. + // Define Pointer and Variable to use for the AccessChain instruction. spirv << "%_ptr_Uniform_deep_struct = OpTypePointer Uniform %s_depth_" << depth << "\n"; spirv << "%deep_var = OpVariable %_ptr_Uniform_deep_struct Uniform\n"; @@ -2322,8 +2037,8 @@ TEST_F(ValidateIdWithMessage, OpInBoundsAccessChainTooManyIndexesGood) { %my_label = OpLabel )"; - // OpAccessChain with 'n' indexes (n = depth) - spirv << "%entry = OpInBoundsAccessChain %_ptr_Uniform_float %deep_var"; + // AccessChain with 'n' indexes (n = depth) + spirv << "%entry = " << GetParam() << " %_ptr_Uniform_float %deep_var"; for (int i = 0; i < depth; ++i) { spirv << " %int_0"; } @@ -2337,11 +2052,12 @@ TEST_F(ValidateIdWithMessage, OpInBoundsAccessChainTooManyIndexesGood) { EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); } -// Invalid: 256 indexes passed to OpInBoundsAccessChain. Limit is 255. -TEST_F(ValidateIdWithMessage, OpInBoundsAccessChainTooManyIndexesBad) { +// Invalid: 256 indexes passed to the access chain instruction. Limit is 255. +TEST_P(AccessChainInstructionTest, AccessChainTooManyIndexesBad) { + const std::string instr = GetParam(); std::ostringstream spirv; spirv << kGLSL450MemoryModel << opAccessChainSpirvSetup; - spirv << "%entry = OpInBoundsAccessChain %_ptr_Private_float %my_matrix"; + spirv << "%entry = " << instr << " %_ptr_Private_float %my_matrix"; for (int i = 0; i < 256; ++i) { spirv << " %int_0"; } @@ -2349,106 +2065,124 @@ TEST_F(ValidateIdWithMessage, OpInBoundsAccessChainTooManyIndexesBad) { OpReturn OpFunctionEnd )"; + const std::string expected_err = "The number of indexes in " + instr + + " may not exceed 255. Found 256 indexes."; CompileSuccessfully(spirv.str()); EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("The number of indexes in OpInBoundsAccessChain may not exceed " - "255. Found 256 indexes.")); + EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err)); } -// Invalid: Index passed to OpInBoundsAccessChain is float (must be integer). -TEST_F(ValidateIdWithMessage, OpInBoundsAccessChainUndefinedIndexBad) { +// Invalid: Index passed to the access chain instruction is float (must be +// integer). +TEST_P(AccessChainInstructionTest, AccessChainUndefinedIndexBad) { + const std::string instr = GetParam(); string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%entry = OpInBoundsAccessChain %_ptr_Private_float %my_matrix %float %int_1 +%entry = )" + instr + + R"( %_ptr_Private_float %my_matrix %float %int_1 OpReturn OpFunctionEnd )"; + const std::string expected_err = + "Indexes passed to " + instr + " must be of type integer."; CompileSuccessfully(spirv); EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr( - "Indexes passed to OpInBoundsAccessChain must be of type integer.")); + EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err)); } -// Invalid: The OpInBoundsAccessChain index argument that indexes into a struct -// must be of type OpConstant. -TEST_F(ValidateIdWithMessage, OpInBoundsAccessChainStructIndexNotConstantBad) { +// Invalid: The index argument that indexes into a struct must be of type +// OpConstant. +TEST_P(AccessChainInstructionTest, AccessChainStructIndexNotConstantBad) { + const std::string instr = GetParam(); string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%f = OpInBoundsAccessChain %_ptr_Uniform_float %blockName_var %int_0 %spec_int %int_2 +%f = )" + instr + R"( %_ptr_Uniform_float %blockName_var %int_0 %spec_int %int_2 OpReturn OpFunctionEnd )"; + const std::string expected_err = + "The passed to " + instr + + " to index into a structure must be an OpConstant."; CompileSuccessfully(spirv); EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("The passed to OpInBoundsAccessChain to index into a " - "structure must be an OpConstant.")); + EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err)); } // Invalid: Indexing up to a vec4 granularity, but result type expected float. -TEST_F(ValidateIdWithMessage, - OpInBoundsAccessChainStructResultTypeDoesntMatchIndexedTypeBad) { +TEST_P(AccessChainInstructionTest, + AccessChainStructResultTypeDoesntMatchIndexedTypeBad) { + const std::string instr = GetParam(); string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%entry = OpInBoundsAccessChain %_ptr_Uniform_float %blockName_var %int_0 %int_1 %int_2 +%entry = )" + instr + + R"( %_ptr_Uniform_float %blockName_var %int_0 %int_1 %int_2 OpReturn OpFunctionEnd )"; + const std::string expected_err = instr + + " result type (OpTypeFloat) does not match " + "the type that results from indexing into " + "the base (OpTypeVector)."; CompileSuccessfully(spirv); EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("OpInBoundsAccessChain result type (OpTypeFloat) does " - "not match the type that results from indexing into " - "the base (OpTypeVector).")); + EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err)); } // Invalid: Reach non-composite type (bool) when unused indexes remain. -TEST_F(ValidateIdWithMessage, OpInBoundsAccessChainStructTooManyIndexesBad) { +TEST_P(AccessChainInstructionTest, AccessChainStructTooManyIndexesBad) { + const std::string instr = GetParam(); string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%entry = OpInBoundsAccessChain %_ptr_Uniform_float %blockName_var %int_0 %int_2 %int_2 +%entry = )" + instr + + R"( %_ptr_Uniform_float %blockName_var %int_0 %int_2 %int_2 OpReturn OpFunctionEnd )"; + const std::string expected_err = instr + + " reached non-composite type while " + "indexes still remain to be traversed."; CompileSuccessfully(spirv); EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpInBoundsAccessChain reached non-composite type while " - "indexes still remain to be traversed.")); + EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err)); } // Invalid: Trying to find index 3 of the struct that has only 3 members. -TEST_F(ValidateIdWithMessage, OpInBoundsAccessChainStructIndexOutOfBoundBad) { +TEST_P(AccessChainInstructionTest, AccessChainStructIndexOutOfBoundBad) { + const std::string instr = GetParam(); string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%entry = OpInBoundsAccessChain %_ptr_Uniform_float %blockName_var %int_3 %int_2 %int_2 +%entry = )" + instr + + R"( %_ptr_Uniform_float %blockName_var %int_3 %int_2 %int_2 OpReturn OpFunctionEnd )"; + const std::string expected_err = "Index is out of bound: " + instr + + " can not find index 3 into the structure " + " '26'. This structure has 3 members. " + "Largest valid index is 2."; CompileSuccessfully(spirv); EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("Index is out of bound: OpInBoundsAccessChain can not find " - "index 3 into the structure '26'. This structure " - "has 3 members. Largest valid index is 2.")); + EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err)); } // Valid: Tests that we can index into Struct, Array, Matrix, and Vector! -TEST_F(ValidateIdWithMessage, OpInBoundsAccessChainIndexIntoAllTypesGood) { +TEST_P(AccessChainInstructionTest, AccessChainIndexIntoAllTypesGood) { // indexes that we are passing are: 0, 3, 1, 2, 0 // 0 will select the struct_s within the base struct (blockName) // 3 will select the Array that contains 5 matrices // 1 will select the Matrix that is at index 1 of the array // 2 will select the column (which is a vector) within the matrix at index 2 // 0 will select the element at the index 0 of the vector. (which is a float). - string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%ss = OpInBoundsAccessChain %_ptr_Uniform_struct_s %blockName_var %int_0 -%sa = OpInBoundsAccessChain %_ptr_Uniform_array5_mat4x3 %blockName_var %int_0 %int_3 -%sm = OpInBoundsAccessChain %_ptr_Uniform_mat4x3 %blockName_var %int_0 %int_3 %int_1 -%sc = OpInBoundsAccessChain %_ptr_Uniform_v3float %blockName_var %int_0 %int_3 %int_1 %int_2 -%entry = OpInBoundsAccessChain %_ptr_Uniform_float %blockName_var %int_0 %int_3 %int_1 %int_2 %int_0 + const std::string instr = GetParam(); + string spirv = + kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( +%ss = )" + + instr + R"( %_ptr_Uniform_struct_s %blockName_var %int_0 +%sa = )" + + instr + R"( %_ptr_Uniform_array5_mat4x3 %blockName_var %int_0 %int_3 +%sm = )" + + instr + R"( %_ptr_Uniform_mat4x3 %blockName_var %int_0 %int_3 %int_1 +%sc = )" + + instr + + R"( %_ptr_Uniform_v3float %blockName_var %int_0 %int_3 %int_1 %int_2 +%entry = )" + + instr + + R"( %_ptr_Uniform_float %blockName_var %int_0 %int_3 %int_1 %int_2 %int_0 OpReturn OpFunctionEnd )"; @@ -2457,9 +2191,11 @@ OpFunctionEnd } // Valid: Access an element of OpTypeRuntimeArray. -TEST_F(ValidateIdWithMessage, OpInBoundsAccessChainIndexIntoRuntimeArrayGood) { +TEST_P(AccessChainInstructionTest, AccessChainIndexIntoRuntimeArrayGood) { string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%runtime_arr_entry = OpInBoundsAccessChain %_ptr_Uniform_float %blockName_var %int_2 %int_0 +%runtime_arr_entry = )" + + GetParam() + + R"( %_ptr_Uniform_float %blockName_var %int_2 %int_0 OpReturn OpFunctionEnd )"; @@ -2468,54 +2204,66 @@ OpFunctionEnd } // Invalid: Unused index when accessing OpTypeRuntimeArray. -TEST_F(ValidateIdWithMessage, OpInBoundsAccessChainIndexIntoRuntimeArrayBad) { +TEST_P(AccessChainInstructionTest, AccessChainIndexIntoRuntimeArrayBad) { + const std::string instr = GetParam(); string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%runtime_arr_entry = OpInBoundsAccessChain %_ptr_Uniform_float %blockName_var %int_2 %int_0 %int_1 +%runtime_arr_entry = )" + + instr + + R"( %_ptr_Uniform_float %blockName_var %int_2 %int_0 %int_1 OpReturn OpFunctionEnd )"; + const std::string expected_err = + instr + + " reached non-composite type while indexes still remain to be traversed."; CompileSuccessfully(spirv); EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpInBoundsAccessChain reached non-composite type while " - "indexes still remain to be traversed.")); + EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err)); } -// Invalid: Reached scalar type before arguments to OpInBoundsAccessChain +// Invalid: Reached scalar type before arguments to the access chain instruction // finished. -TEST_F(ValidateIdWithMessage, - OpInBoundsAccessChainMatrixMoreArgsThanNeededBad) { +TEST_P(AccessChainInstructionTest, AccessChainMatrixMoreArgsThanNeededBad) { + const std::string instr = GetParam(); string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%entry = OpInBoundsAccessChain %_ptr_Private_float %my_matrix %int_0 %int_1 %int_0 +%entry = )" + instr + + R"( %_ptr_Private_float %my_matrix %int_0 %int_1 %int_0 OpReturn OpFunctionEnd )"; + const std::string expected_err = instr + + " reached non-composite type while " + "indexes still remain to be traversed."; CompileSuccessfully(spirv); EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpInBoundsAccessChain reached non-composite type while " - "indexes still remain to be traversed.")); + EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err)); } // Invalid: The result type and the type indexed into do not match. -TEST_F(ValidateIdWithMessage, - OpInBoundsAccessChainResultTypeDoesntMatchIndexedTypeBad) { +TEST_P(AccessChainInstructionTest, + AccessChainResultTypeDoesntMatchIndexedTypeBad) { + const std::string instr = GetParam(); string spirv = kGLSL450MemoryModel + opAccessChainSpirvSetup + R"( -%entry = OpInBoundsAccessChain %_ptr_Private_mat4x3 %my_matrix %int_0 %int_1 +%entry = )" + instr + + R"( %_ptr_Private_mat4x3 %my_matrix %int_0 %int_1 OpReturn OpFunctionEnd )"; + const std::string expected_err = instr + + " result type (OpTypeMatrix) does not match " + "the type that results from indexing into " + "the base (OpTypeFloat)."; CompileSuccessfully(spirv); EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT( - getDiagnosticString(), - HasSubstr("OpInBoundsAccessChain result type (OpTypeMatrix) does not " - "match the type that results from indexing into the " - "base (OpTypeFloat).")); + EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err)); } +// Run tests for Access Chain Instructions. +INSTANTIATE_TEST_CASE_P(CheckAccessChainInstructions, + AccessChainInstructionTest, + ::testing::Values("OpAccessChain", + "OpInBoundsAccessChain")); + // TODO: OpArrayLength // TODO: OpImagePointer // TODO: OpGenericPtrMemSemantics -- 2.7.4