Dejan Mircevski | b6fe02f | 2016-01-07 13:44:22 -0500 | [diff] [blame] | 1 | // Copyright (c) 2015-2016 The Khronos Group Inc. |
David Neto | abe51c4 | 2015-09-11 22:35:04 -0400 | [diff] [blame] | 2 | // |
David Neto | 9fc8658 | 2016-09-01 15:33:59 -0400 | [diff] [blame] | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
David Neto | abe51c4 | 2015-09-11 22:35:04 -0400 | [diff] [blame] | 6 | // |
David Neto | 9fc8658 | 2016-09-01 15:33:59 -0400 | [diff] [blame] | 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
David Neto | abe51c4 | 2015-09-11 22:35:04 -0400 | [diff] [blame] | 8 | // |
David Neto | 9fc8658 | 2016-09-01 15:33:59 -0400 | [diff] [blame] | 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
David Neto | abe51c4 | 2015-09-11 22:35:04 -0400 | [diff] [blame] | 14 | |
| 15 | // Assembler tests for instructions in the "Type-Declaration" section of the |
| 16 | // SPIR-V spec. |
| 17 | |
dan sinclair | eda2cfb | 2018-08-03 15:06:09 -0400 | [diff] [blame] | 18 | #include <string> |
| 19 | #include <vector> |
David Neto | abe51c4 | 2015-09-11 22:35:04 -0400 | [diff] [blame] | 20 | |
David Neto | d9ad050 | 2015-11-24 18:37:24 -0500 | [diff] [blame] | 21 | #include "gmock/gmock.h" |
dan sinclair | eda2cfb | 2018-08-03 15:06:09 -0400 | [diff] [blame] | 22 | #include "test/test_fixture.h" |
| 23 | #include "test/unit_spirv.h" |
David Neto | abe51c4 | 2015-09-11 22:35:04 -0400 | [diff] [blame] | 24 | |
dan sinclair | 2cce2c5 | 2018-07-11 09:24:49 -0400 | [diff] [blame] | 25 | namespace spvtools { |
David Neto | abe51c4 | 2015-09-11 22:35:04 -0400 | [diff] [blame] | 26 | namespace { |
| 27 | |
David Neto | 3d2bf53 | 2015-10-01 16:58:17 -0400 | [diff] [blame] | 28 | using spvtest::EnumCase; |
David Neto | abe51c4 | 2015-09-11 22:35:04 -0400 | [diff] [blame] | 29 | using spvtest::MakeInstruction; |
| 30 | using ::testing::Eq; |
| 31 | |
David Neto | b30a0c5 | 2015-09-16 15:56:43 -0400 | [diff] [blame] | 32 | // Test Dim enums via OpTypeImage |
| 33 | |
Dejan Mircevski | 52ff534 | 2015-10-09 16:48:28 -0400 | [diff] [blame] | 34 | using DimTest = |
Lei Zhang | b36e704 | 2015-10-28 13:40:52 -0400 | [diff] [blame] | 35 | spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<SpvDim>>>; |
David Neto | b30a0c5 | 2015-09-16 15:56:43 -0400 | [diff] [blame] | 36 | |
| 37 | TEST_P(DimTest, AnyDim) { |
David Neto | d9ad050 | 2015-11-24 18:37:24 -0500 | [diff] [blame] | 38 | const std::string input = |
| 39 | "%1 = OpTypeImage %2 " + GetParam().name() + " 2 3 0 4 Rgba8\n"; |
David Neto | b30a0c5 | 2015-09-16 15:56:43 -0400 | [diff] [blame] | 40 | EXPECT_THAT( |
| 41 | CompiledInstructions(input), |
Lei Zhang | 1a0334e | 2015-11-02 09:41:20 -0500 | [diff] [blame] | 42 | Eq(MakeInstruction(SpvOpTypeImage, {1, 2, GetParam().value(), 2, 3, 0, 4, |
| 43 | SpvImageFormatRgba8}))); |
David Neto | d9ad050 | 2015-11-24 18:37:24 -0500 | [diff] [blame] | 44 | |
| 45 | // Check the disassembler as well. |
| 46 | EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(input)); |
David Neto | b30a0c5 | 2015-09-16 15:56:43 -0400 | [diff] [blame] | 47 | } |
| 48 | |
| 49 | // clang-format off |
Lei Zhang | b36e704 | 2015-10-28 13:40:52 -0400 | [diff] [blame] | 50 | #define CASE(NAME) {SpvDim##NAME, #NAME} |
Steven Perron | 464111e | 2019-01-29 18:56:52 -0500 | [diff] [blame] | 51 | INSTANTIATE_TEST_SUITE_P( |
David Neto | b30a0c5 | 2015-09-16 15:56:43 -0400 | [diff] [blame] | 52 | TextToBinaryDim, DimTest, |
Lei Zhang | b36e704 | 2015-10-28 13:40:52 -0400 | [diff] [blame] | 53 | ::testing::ValuesIn(std::vector<EnumCase<SpvDim>>{ |
David Neto | b30a0c5 | 2015-09-16 15:56:43 -0400 | [diff] [blame] | 54 | CASE(1D), |
| 55 | CASE(2D), |
| 56 | CASE(3D), |
| 57 | CASE(Cube), |
| 58 | CASE(Rect), |
| 59 | CASE(Buffer), |
David Neto | d02f68a | 2015-11-11 12:32:21 -0500 | [diff] [blame] | 60 | CASE(SubpassData), |
Steven Perron | 464111e | 2019-01-29 18:56:52 -0500 | [diff] [blame] | 61 | })); |
David Neto | b30a0c5 | 2015-09-16 15:56:43 -0400 | [diff] [blame] | 62 | #undef CASE |
| 63 | // clang-format on |
| 64 | |
Dejan Mircevski | 2fd3792 | 2015-10-13 11:46:09 -0400 | [diff] [blame] | 65 | TEST_F(DimTest, WrongDim) { |
| 66 | EXPECT_THAT(CompileFailure("%i = OpTypeImage %t xxyyzz 1 2 3 4 R8"), |
| 67 | Eq("Invalid dimensionality 'xxyyzz'.")); |
| 68 | } |
| 69 | |
David Neto | b30a0c5 | 2015-09-16 15:56:43 -0400 | [diff] [blame] | 70 | // Test ImageFormat enums via OpTypeImage |
| 71 | |
David Neto | 1b5fd49 | 2015-09-21 11:36:44 -0400 | [diff] [blame] | 72 | using ImageFormatTest = spvtest::TextToBinaryTestBase< |
Lei Zhang | b36e704 | 2015-10-28 13:40:52 -0400 | [diff] [blame] | 73 | ::testing::TestWithParam<EnumCase<SpvImageFormat>>>; |
David Neto | b30a0c5 | 2015-09-16 15:56:43 -0400 | [diff] [blame] | 74 | |
David Neto | 2889a0c | 2016-02-15 13:50:00 -0500 | [diff] [blame] | 75 | TEST_P(ImageFormatTest, AnyImageFormatAndNoAccessQualifier) { |
Dejan Mircevski | d062f8b | 2015-10-13 12:46:13 -0400 | [diff] [blame] | 76 | const std::string input = |
David Neto | d9ad050 | 2015-11-24 18:37:24 -0500 | [diff] [blame] | 77 | "%1 = OpTypeImage %2 1D 2 3 0 4 " + GetParam().name() + "\n"; |
David Neto | b30a0c5 | 2015-09-16 15:56:43 -0400 | [diff] [blame] | 78 | EXPECT_THAT(CompiledInstructions(input), |
Lei Zhang | 1a0334e | 2015-11-02 09:41:20 -0500 | [diff] [blame] | 79 | Eq(MakeInstruction(SpvOpTypeImage, {1, 2, SpvDim1D, 2, 3, 0, 4, |
| 80 | GetParam().value()}))); |
David Neto | d9ad050 | 2015-11-24 18:37:24 -0500 | [diff] [blame] | 81 | // Check the disassembler as well. |
| 82 | EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(input)); |
David Neto | b30a0c5 | 2015-09-16 15:56:43 -0400 | [diff] [blame] | 83 | } |
| 84 | |
| 85 | // clang-format off |
Lei Zhang | b36e704 | 2015-10-28 13:40:52 -0400 | [diff] [blame] | 86 | #define CASE(NAME) {SpvImageFormat##NAME, #NAME} |
Steven Perron | 464111e | 2019-01-29 18:56:52 -0500 | [diff] [blame] | 87 | INSTANTIATE_TEST_SUITE_P( |
David Neto | b30a0c5 | 2015-09-16 15:56:43 -0400 | [diff] [blame] | 88 | TextToBinaryImageFormat, ImageFormatTest, |
Lei Zhang | b36e704 | 2015-10-28 13:40:52 -0400 | [diff] [blame] | 89 | ::testing::ValuesIn(std::vector<EnumCase<SpvImageFormat>>{ |
David Neto | b30a0c5 | 2015-09-16 15:56:43 -0400 | [diff] [blame] | 90 | CASE(Unknown), |
| 91 | CASE(Rgba32f), |
| 92 | CASE(Rgba16f), |
| 93 | CASE(R32f), |
| 94 | CASE(Rgba8), |
| 95 | CASE(Rgba8Snorm), |
| 96 | CASE(Rg32f), |
| 97 | CASE(Rg16f), |
| 98 | CASE(R11fG11fB10f), |
| 99 | CASE(R16f), |
| 100 | CASE(Rgba16), |
| 101 | CASE(Rgb10A2), |
| 102 | CASE(Rg16), |
| 103 | CASE(Rg8), |
| 104 | CASE(R16), |
| 105 | CASE(R8), |
| 106 | CASE(Rgba16Snorm), |
| 107 | CASE(Rg16Snorm), |
| 108 | CASE(Rg8Snorm), |
| 109 | CASE(R16Snorm), |
| 110 | CASE(R8Snorm), |
| 111 | CASE(Rgba32i), |
| 112 | CASE(Rgba16i), |
| 113 | CASE(Rgba8i), |
| 114 | CASE(R32i), |
| 115 | CASE(Rg32i), |
| 116 | CASE(Rg16i), |
| 117 | CASE(Rg8i), |
| 118 | CASE(R16i), |
| 119 | CASE(R8i), |
| 120 | CASE(Rgba32ui), |
| 121 | CASE(Rgba16ui), |
| 122 | CASE(Rgba8ui), |
| 123 | CASE(R32ui), |
| 124 | CASE(Rgb10a2ui), |
| 125 | CASE(Rg32ui), |
| 126 | CASE(Rg16ui), |
| 127 | CASE(Rg8ui), |
| 128 | CASE(R16ui), |
| 129 | CASE(R8ui), |
Steven Perron | 464111e | 2019-01-29 18:56:52 -0500 | [diff] [blame] | 130 | })); |
David Neto | b30a0c5 | 2015-09-16 15:56:43 -0400 | [diff] [blame] | 131 | #undef CASE |
| 132 | // clang-format on |
| 133 | |
Dejan Mircevski | 971b344 | 2015-10-13 12:54:47 -0400 | [diff] [blame] | 134 | TEST_F(ImageFormatTest, WrongFormat) { |
| 135 | EXPECT_THAT(CompileFailure("%r = OpTypeImage %t 1D 2 3 0 4 xxyyzz"), |
| 136 | Eq("Invalid image format 'xxyyzz'.")); |
| 137 | } |
| 138 | |
David Neto | 2889a0c | 2016-02-15 13:50:00 -0500 | [diff] [blame] | 139 | // Test AccessQualifier enums via OpTypeImage. |
| 140 | using ImageAccessQualifierTest = spvtest::TextToBinaryTestBase< |
| 141 | ::testing::TestWithParam<EnumCase<SpvAccessQualifier>>>; |
| 142 | |
| 143 | TEST_P(ImageAccessQualifierTest, AnyAccessQualifier) { |
| 144 | const std::string input = |
| 145 | "%1 = OpTypeImage %2 1D 2 3 0 4 Rgba8 " + GetParam().name() + "\n"; |
| 146 | EXPECT_THAT(CompiledInstructions(input), |
| 147 | Eq(MakeInstruction(SpvOpTypeImage, |
| 148 | {1, 2, SpvDim1D, 2, 3, 0, 4, |
| 149 | SpvImageFormatRgba8, GetParam().value()}))); |
| 150 | // Check the disassembler as well. |
| 151 | EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(input)); |
| 152 | } |
| 153 | |
| 154 | // clang-format off |
| 155 | #define CASE(NAME) {SpvAccessQualifier##NAME, #NAME} |
Steven Perron | 464111e | 2019-01-29 18:56:52 -0500 | [diff] [blame] | 156 | INSTANTIATE_TEST_SUITE_P( |
David Neto | 2889a0c | 2016-02-15 13:50:00 -0500 | [diff] [blame] | 157 | AccessQualifier, ImageAccessQualifierTest, |
| 158 | ::testing::ValuesIn(std::vector<EnumCase<SpvAccessQualifier>>{ |
| 159 | CASE(ReadOnly), |
| 160 | CASE(WriteOnly), |
| 161 | CASE(ReadWrite), |
Steven Perron | 464111e | 2019-01-29 18:56:52 -0500 | [diff] [blame] | 162 | })); |
David Neto | 2889a0c | 2016-02-15 13:50:00 -0500 | [diff] [blame] | 163 | // clang-format on |
| 164 | #undef CASE |
| 165 | |
David Neto | b30a0c5 | 2015-09-16 15:56:43 -0400 | [diff] [blame] | 166 | // Test AccessQualifier enums via OpTypePipe. |
David Neto | f7ee0ca | 2015-09-16 15:29:02 -0400 | [diff] [blame] | 167 | |
David Neto | 1b5fd49 | 2015-09-21 11:36:44 -0400 | [diff] [blame] | 168 | using OpTypePipeTest = spvtest::TextToBinaryTestBase< |
Lei Zhang | b36e704 | 2015-10-28 13:40:52 -0400 | [diff] [blame] | 169 | ::testing::TestWithParam<EnumCase<SpvAccessQualifier>>>; |
David Neto | abe51c4 | 2015-09-11 22:35:04 -0400 | [diff] [blame] | 170 | |
| 171 | TEST_P(OpTypePipeTest, AnyAccessQualifier) { |
David Neto | 2889a0c | 2016-02-15 13:50:00 -0500 | [diff] [blame] | 172 | const std::string input = "%1 = OpTypePipe " + GetParam().name() + "\n"; |
David Neto | e0890da | 2015-09-24 15:45:59 -0400 | [diff] [blame] | 173 | EXPECT_THAT(CompiledInstructions(input), |
Lei Zhang | b36e704 | 2015-10-28 13:40:52 -0400 | [diff] [blame] | 174 | Eq(MakeInstruction(SpvOpTypePipe, {1, GetParam().value()}))); |
David Neto | 2889a0c | 2016-02-15 13:50:00 -0500 | [diff] [blame] | 175 | // Check the disassembler as well. |
| 176 | EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(input)); |
David Neto | abe51c4 | 2015-09-11 22:35:04 -0400 | [diff] [blame] | 177 | } |
| 178 | |
| 179 | // clang-format off |
Lei Zhang | b36e704 | 2015-10-28 13:40:52 -0400 | [diff] [blame] | 180 | #define CASE(NAME) {SpvAccessQualifier##NAME, #NAME} |
Steven Perron | 464111e | 2019-01-29 18:56:52 -0500 | [diff] [blame] | 181 | INSTANTIATE_TEST_SUITE_P( |
David Neto | f7ee0ca | 2015-09-16 15:29:02 -0400 | [diff] [blame] | 182 | TextToBinaryTypePipe, OpTypePipeTest, |
Lei Zhang | b36e704 | 2015-10-28 13:40:52 -0400 | [diff] [blame] | 183 | ::testing::ValuesIn(std::vector<EnumCase<SpvAccessQualifier>>{ |
Andrew Woloszyn | f2d0775 | 2015-09-18 11:50:54 -0400 | [diff] [blame] | 184 | CASE(ReadOnly), |
| 185 | CASE(WriteOnly), |
| 186 | CASE(ReadWrite), |
Steven Perron | 464111e | 2019-01-29 18:56:52 -0500 | [diff] [blame] | 187 | })); |
David Neto | abe51c4 | 2015-09-11 22:35:04 -0400 | [diff] [blame] | 188 | #undef CASE |
| 189 | // clang-format on |
| 190 | |
Dejan Mircevski | 10fa49c | 2015-10-13 15:25:31 -0400 | [diff] [blame] | 191 | TEST_F(OpTypePipeTest, WrongAccessQualifier) { |
| 192 | EXPECT_THAT(CompileFailure("%1 = OpTypePipe xxyyzz"), |
| 193 | Eq("Invalid access qualifier 'xxyyzz'.")); |
| 194 | } |
| 195 | |
Dejan Mircevski | 52ff534 | 2015-10-09 16:48:28 -0400 | [diff] [blame] | 196 | using OpTypeForwardPointerTest = spvtest::TextToBinaryTest; |
| 197 | |
| 198 | #define CASE(storage_class) \ |
| 199 | do { \ |
| 200 | EXPECT_THAT( \ |
| 201 | CompiledInstructions("OpTypeForwardPointer %pt " #storage_class), \ |
Lei Zhang | b36e704 | 2015-10-28 13:40:52 -0400 | [diff] [blame] | 202 | Eq(MakeInstruction(SpvOpTypeForwardPointer, \ |
| 203 | {1, SpvStorageClass##storage_class}))); \ |
Dejan Mircevski | 52ff534 | 2015-10-09 16:48:28 -0400 | [diff] [blame] | 204 | } while (0) |
| 205 | |
| 206 | TEST_F(OpTypeForwardPointerTest, ValidStorageClass) { |
| 207 | CASE(UniformConstant); |
| 208 | CASE(Input); |
| 209 | CASE(Uniform); |
| 210 | CASE(Output); |
David Neto | d02f68a | 2015-11-11 12:32:21 -0500 | [diff] [blame] | 211 | CASE(Workgroup); |
| 212 | CASE(CrossWorkgroup); |
| 213 | CASE(Private); |
Dejan Mircevski | 52ff534 | 2015-10-09 16:48:28 -0400 | [diff] [blame] | 214 | CASE(Function); |
| 215 | CASE(Generic); |
| 216 | CASE(PushConstant); |
| 217 | CASE(AtomicCounter); |
| 218 | CASE(Image); |
David Neto | bf68c81 | 2017-03-25 21:12:22 -0400 | [diff] [blame] | 219 | CASE(StorageBuffer); |
Dejan Mircevski | 52ff534 | 2015-10-09 16:48:28 -0400 | [diff] [blame] | 220 | } |
| 221 | |
| 222 | #undef CASE |
| 223 | |
| 224 | TEST_F(OpTypeForwardPointerTest, MissingType) { |
| 225 | EXPECT_THAT(CompileFailure("OpTypeForwardPointer"), |
| 226 | Eq("Expected operand, found end of stream.")); |
| 227 | } |
| 228 | |
| 229 | TEST_F(OpTypeForwardPointerTest, MissingClass) { |
| 230 | EXPECT_THAT(CompileFailure("OpTypeForwardPointer %pt"), |
| 231 | Eq("Expected operand, found end of stream.")); |
| 232 | } |
| 233 | |
| 234 | TEST_F(OpTypeForwardPointerTest, WrongClass) { |
| 235 | EXPECT_THAT(CompileFailure("OpTypeForwardPointer %pt xxyyzz"), |
| 236 | Eq("Invalid storage class 'xxyyzz'.")); |
| 237 | } |
| 238 | |
Dejan Mircevski | 45d391b | 2016-04-27 15:41:58 -0400 | [diff] [blame] | 239 | using OpSizeOfTest = spvtest::TextToBinaryTest; |
| 240 | |
David Neto | 8d65c89 | 2018-06-19 09:54:33 -0400 | [diff] [blame] | 241 | // We should be able to assemble it. Validation checks are in another test |
| 242 | // file. |
| 243 | TEST_F(OpSizeOfTest, OpcodeAssemblesInV10) { |
| 244 | EXPECT_THAT( |
| 245 | CompiledInstructions("%1 = OpSizeOf %2 %3", SPV_ENV_UNIVERSAL_1_0), |
| 246 | Eq(MakeInstruction(SpvOpSizeOf, {1, 2, 3}))); |
Dejan Mircevski | 45d391b | 2016-04-27 15:41:58 -0400 | [diff] [blame] | 247 | } |
| 248 | |
| 249 | TEST_F(OpSizeOfTest, ArgumentCount) { |
| 250 | EXPECT_THAT( |
| 251 | CompileFailure("OpSizeOf", SPV_ENV_UNIVERSAL_1_1), |
| 252 | Eq("Expected <result-id> at the beginning of an instruction, found " |
| 253 | "'OpSizeOf'.")); |
| 254 | EXPECT_THAT(CompileFailure("%res = OpSizeOf OpNop", SPV_ENV_UNIVERSAL_1_1), |
| 255 | Eq("Expected operand, found next instruction instead.")); |
| 256 | EXPECT_THAT( |
| 257 | CompiledInstructions("%1 = OpSizeOf %2 %3", SPV_ENV_UNIVERSAL_1_1), |
| 258 | Eq(MakeInstruction(SpvOpSizeOf, {1, 2, 3}))); |
| 259 | EXPECT_THAT( |
| 260 | CompileFailure("%1 = OpSizeOf %2 %3 44 55 ", SPV_ENV_UNIVERSAL_1_1), |
| 261 | Eq("Expected <opcode> or <result-id> at the beginning of an instruction, " |
| 262 | "found '44'.")); |
| 263 | } |
| 264 | |
| 265 | TEST_F(OpSizeOfTest, ArgumentTypes) { |
| 266 | EXPECT_THAT(CompileFailure("%1 = OpSizeOf 2 %3", SPV_ENV_UNIVERSAL_1_1), |
| 267 | Eq("Expected id to start with %.")); |
| 268 | EXPECT_THAT(CompileFailure("%1 = OpSizeOf %2 \"abc\"", SPV_ENV_UNIVERSAL_1_1), |
| 269 | Eq("Expected id to start with %.")); |
| 270 | } |
| 271 | |
David Neto | abe51c4 | 2015-09-11 22:35:04 -0400 | [diff] [blame] | 272 | // TODO(dneto): OpTypeVoid |
| 273 | // TODO(dneto): OpTypeBool |
| 274 | // TODO(dneto): OpTypeInt |
| 275 | // TODO(dneto): OpTypeFloat |
| 276 | // TODO(dneto): OpTypeVector |
| 277 | // TODO(dneto): OpTypeMatrix |
| 278 | // TODO(dneto): OpTypeImage |
| 279 | // TODO(dneto): OpTypeSampler |
| 280 | // TODO(dneto): OpTypeSampledImage |
| 281 | // TODO(dneto): OpTypeArray |
| 282 | // TODO(dneto): OpTypeRuntimeArray |
| 283 | // TODO(dneto): OpTypeStruct |
| 284 | // TODO(dneto): OpTypeOpaque |
| 285 | // TODO(dneto): OpTypePointer |
| 286 | // TODO(dneto): OpTypeFunction |
| 287 | // TODO(dneto): OpTypeEvent |
| 288 | // TODO(dneto): OpTypeDeviceEvent |
| 289 | // TODO(dneto): OpTypeReserveId |
| 290 | // TODO(dneto): OpTypeQueue |
David Neto | abe51c4 | 2015-09-11 22:35:04 -0400 | [diff] [blame] | 291 | |
dan sinclair | 2cce2c5 | 2018-07-11 09:24:49 -0400 | [diff] [blame] | 292 | } // namespace |
| 293 | } // namespace spvtools |