Antonio Maiorano | 9970ec6 | 2021-03-18 17:59:54 +0000 | [diff] [blame] | 1 | // Copyright 2021 The Tint Authors. |
| 2 | // |
| 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 |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 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. |
| 14 | |
| 15 | #include "src/ast/access_decoration.h" |
| 16 | #include "src/ast/constant_id_decoration.h" |
Antonio Maiorano | 03c01b5 | 2021-03-19 14:04:51 +0000 | [diff] [blame] | 17 | #include "src/ast/return_statement.h" |
Antonio Maiorano | 9970ec6 | 2021-03-18 17:59:54 +0000 | [diff] [blame] | 18 | #include "src/ast/stage_decoration.h" |
| 19 | #include "src/ast/struct_block_decoration.h" |
| 20 | #include "src/ast/workgroup_decoration.h" |
| 21 | #include "src/resolver/resolver.h" |
| 22 | #include "src/resolver/resolver_test_helper.h" |
| 23 | |
| 24 | #include "gmock/gmock.h" |
| 25 | |
| 26 | namespace tint { |
Antonio Maiorano | fc03a46 | 2021-04-16 02:36:44 +0000 | [diff] [blame] | 27 | namespace resolver { |
| 28 | |
| 29 | namespace DecorationTests { |
Antonio Maiorano | 9970ec6 | 2021-03-18 17:59:54 +0000 | [diff] [blame] | 30 | namespace { |
| 31 | |
| 32 | enum class DecorationKind { |
| 33 | kAccess, |
| 34 | kAlign, |
| 35 | kBinding, |
| 36 | kBuiltin, |
| 37 | kConstantId, |
| 38 | kGroup, |
| 39 | kLocation, |
| 40 | kOffset, |
| 41 | kSize, |
| 42 | kStage, |
| 43 | kStride, |
| 44 | kStructBlock, |
| 45 | kWorkgroup, |
| 46 | }; |
| 47 | struct TestParams { |
| 48 | DecorationKind kind; |
| 49 | bool should_pass; |
| 50 | }; |
Antonio Maiorano | fc03a46 | 2021-04-16 02:36:44 +0000 | [diff] [blame] | 51 | struct TestWithParams : ResolverTestWithParam<TestParams> {}; |
Antonio Maiorano | 9970ec6 | 2021-03-18 17:59:54 +0000 | [diff] [blame] | 52 | |
Antonio Maiorano | fc03a46 | 2021-04-16 02:36:44 +0000 | [diff] [blame] | 53 | static ast::Decoration* createDecoration(const Source& source, |
| 54 | ProgramBuilder& builder, |
| 55 | DecorationKind kind) { |
Antonio Maiorano | 9970ec6 | 2021-03-18 17:59:54 +0000 | [diff] [blame] | 56 | switch (kind) { |
| 57 | case DecorationKind::kAccess: |
| 58 | return builder.create<ast::AccessDecoration>( |
| 59 | source, ast::AccessControl::kReadOnly); |
| 60 | case DecorationKind::kAlign: |
| 61 | return builder.create<ast::StructMemberAlignDecoration>(source, 4u); |
| 62 | case DecorationKind::kBinding: |
| 63 | return builder.create<ast::BindingDecoration>(source, 1); |
| 64 | case DecorationKind::kBuiltin: |
| 65 | return builder.create<ast::BuiltinDecoration>(source, |
| 66 | ast::Builtin::kPosition); |
| 67 | case DecorationKind::kConstantId: |
| 68 | return builder.create<ast::ConstantIdDecoration>(source, 0u); |
| 69 | case DecorationKind::kGroup: |
| 70 | return builder.create<ast::GroupDecoration>(source, 1u); |
| 71 | case DecorationKind::kLocation: |
| 72 | return builder.create<ast::LocationDecoration>(source, 1); |
| 73 | case DecorationKind::kOffset: |
| 74 | return builder.create<ast::StructMemberOffsetDecoration>(source, 4u); |
| 75 | case DecorationKind::kSize: |
| 76 | return builder.create<ast::StructMemberSizeDecoration>(source, 4u); |
| 77 | case DecorationKind::kStage: |
| 78 | return builder.create<ast::StageDecoration>(source, |
| 79 | ast::PipelineStage::kCompute); |
| 80 | case DecorationKind::kStride: |
| 81 | return builder.create<ast::StrideDecoration>(source, 4u); |
| 82 | case DecorationKind::kStructBlock: |
| 83 | return builder.create<ast::StructBlockDecoration>(source); |
| 84 | case DecorationKind::kWorkgroup: |
| 85 | return builder.create<ast::WorkgroupDecoration>(source, 1u, 1u, 1u); |
| 86 | } |
| 87 | return nullptr; |
| 88 | } |
| 89 | |
Antonio Maiorano | 03c01b5 | 2021-03-19 14:04:51 +0000 | [diff] [blame] | 90 | using FunctionReturnTypeDecorationTest = TestWithParams; |
| 91 | TEST_P(FunctionReturnTypeDecorationTest, IsValid) { |
Antonio Maiorano | fc03a46 | 2021-04-16 02:36:44 +0000 | [diff] [blame] | 92 | auto& params = GetParam(); |
Antonio Maiorano | 03c01b5 | 2021-03-19 14:04:51 +0000 | [diff] [blame] | 93 | |
| 94 | Func("main", ast::VariableList{}, ty.f32(), |
| 95 | ast::StatementList{create<ast::ReturnStatement>(Expr(1.f))}, |
| 96 | ast::DecorationList{ |
| 97 | create<ast::StageDecoration>(ast::PipelineStage::kVertex)}, |
| 98 | ast::DecorationList{createDecoration({}, *this, params.kind)}); |
| 99 | |
| 100 | if (params.should_pass) { |
| 101 | EXPECT_TRUE(r()->Resolve()) << r()->error(); |
| 102 | } else { |
| 103 | EXPECT_FALSE(r()->Resolve()) << r()->error(); |
| 104 | EXPECT_EQ(r()->error(), |
| 105 | "error: decoration is not valid for function return types"); |
| 106 | } |
| 107 | } |
| 108 | INSTANTIATE_TEST_SUITE_P( |
| 109 | ResolverDecorationValidationTest, |
| 110 | FunctionReturnTypeDecorationTest, |
| 111 | testing::Values(TestParams{DecorationKind::kAccess, false}, |
| 112 | TestParams{DecorationKind::kAlign, false}, |
| 113 | TestParams{DecorationKind::kBinding, false}, |
| 114 | TestParams{DecorationKind::kBuiltin, true}, |
| 115 | TestParams{DecorationKind::kConstantId, false}, |
| 116 | TestParams{DecorationKind::kGroup, false}, |
| 117 | TestParams{DecorationKind::kLocation, true}, |
| 118 | TestParams{DecorationKind::kOffset, false}, |
| 119 | TestParams{DecorationKind::kSize, false}, |
| 120 | TestParams{DecorationKind::kStage, false}, |
| 121 | TestParams{DecorationKind::kStride, false}, |
| 122 | TestParams{DecorationKind::kStructBlock, false}, |
| 123 | TestParams{DecorationKind::kWorkgroup, false})); |
| 124 | |
Antonio Maiorano | 9970ec6 | 2021-03-18 17:59:54 +0000 | [diff] [blame] | 125 | using ArrayDecorationTest = TestWithParams; |
Antonio Maiorano | 9970ec6 | 2021-03-18 17:59:54 +0000 | [diff] [blame] | 126 | TEST_P(ArrayDecorationTest, IsValid) { |
Antonio Maiorano | fc03a46 | 2021-04-16 02:36:44 +0000 | [diff] [blame] | 127 | auto& params = GetParam(); |
Antonio Maiorano | 9970ec6 | 2021-03-18 17:59:54 +0000 | [diff] [blame] | 128 | |
| 129 | ast::StructMemberList members{Member( |
Antonio Maiorano | 3751fd2 | 2021-04-19 22:51:23 +0000 | [diff] [blame^] | 130 | "a", create<sem::ArrayType>(ty.f32(), 0, |
| 131 | ast::DecorationList{createDecoration( |
| 132 | Source{{12, 34}}, *this, params.kind)}))}; |
Antonio Maiorano | 9970ec6 | 2021-03-18 17:59:54 +0000 | [diff] [blame] | 133 | auto* s = create<ast::Struct>( |
| 134 | members, ast::DecorationList{create<ast::StructBlockDecoration>()}); |
| 135 | auto* s_ty = ty.struct_("mystruct", s); |
| 136 | AST().AddConstructedType(s_ty); |
| 137 | |
| 138 | WrapInFunction(); |
| 139 | |
| 140 | if (params.should_pass) { |
| 141 | EXPECT_TRUE(r()->Resolve()) << r()->error(); |
| 142 | } else { |
| 143 | EXPECT_FALSE(r()->Resolve()) << r()->error(); |
| 144 | EXPECT_EQ(r()->error(), |
| 145 | "12:34 error: decoration is not valid for array types"); |
| 146 | } |
| 147 | } |
| 148 | INSTANTIATE_TEST_SUITE_P( |
| 149 | ResolverDecorationValidationTest, |
| 150 | ArrayDecorationTest, |
| 151 | testing::Values(TestParams{DecorationKind::kAccess, false}, |
| 152 | TestParams{DecorationKind::kAlign, false}, |
| 153 | TestParams{DecorationKind::kBinding, false}, |
| 154 | TestParams{DecorationKind::kBuiltin, false}, |
| 155 | TestParams{DecorationKind::kConstantId, false}, |
| 156 | TestParams{DecorationKind::kGroup, false}, |
| 157 | TestParams{DecorationKind::kLocation, false}, |
| 158 | TestParams{DecorationKind::kOffset, false}, |
| 159 | TestParams{DecorationKind::kSize, false}, |
| 160 | TestParams{DecorationKind::kStage, false}, |
| 161 | TestParams{DecorationKind::kStride, true}, |
| 162 | TestParams{DecorationKind::kStructBlock, false}, |
| 163 | TestParams{DecorationKind::kWorkgroup, false})); |
| 164 | |
| 165 | using StructDecorationTest = TestWithParams; |
| 166 | TEST_P(StructDecorationTest, IsValid) { |
Antonio Maiorano | fc03a46 | 2021-04-16 02:36:44 +0000 | [diff] [blame] | 167 | auto& params = GetParam(); |
Antonio Maiorano | 9970ec6 | 2021-03-18 17:59:54 +0000 | [diff] [blame] | 168 | |
| 169 | auto* s = create<ast::Struct>(ast::StructMemberList{}, |
| 170 | ast::DecorationList{createDecoration( |
| 171 | Source{{12, 34}}, *this, params.kind)}); |
| 172 | auto* s_ty = ty.struct_("mystruct", s); |
| 173 | AST().AddConstructedType(s_ty); |
| 174 | |
| 175 | WrapInFunction(); |
| 176 | |
| 177 | if (params.should_pass) { |
| 178 | EXPECT_TRUE(r()->Resolve()) << r()->error(); |
| 179 | } else { |
| 180 | EXPECT_FALSE(r()->Resolve()) << r()->error(); |
| 181 | EXPECT_EQ(r()->error(), |
| 182 | "12:34 error: decoration is not valid for struct declarations"); |
| 183 | } |
| 184 | } |
| 185 | INSTANTIATE_TEST_SUITE_P( |
| 186 | ResolverDecorationValidationTest, |
| 187 | StructDecorationTest, |
| 188 | testing::Values(TestParams{DecorationKind::kAccess, false}, |
| 189 | TestParams{DecorationKind::kAlign, false}, |
| 190 | TestParams{DecorationKind::kBinding, false}, |
| 191 | TestParams{DecorationKind::kBuiltin, false}, |
| 192 | TestParams{DecorationKind::kConstantId, false}, |
| 193 | TestParams{DecorationKind::kGroup, false}, |
| 194 | TestParams{DecorationKind::kLocation, false}, |
| 195 | TestParams{DecorationKind::kOffset, false}, |
| 196 | TestParams{DecorationKind::kSize, false}, |
| 197 | TestParams{DecorationKind::kStage, false}, |
| 198 | TestParams{DecorationKind::kStride, false}, |
| 199 | TestParams{DecorationKind::kStructBlock, true}, |
| 200 | TestParams{DecorationKind::kWorkgroup, false})); |
| 201 | |
| 202 | using StructMemberDecorationTest = TestWithParams; |
| 203 | TEST_P(StructMemberDecorationTest, IsValid) { |
Antonio Maiorano | fc03a46 | 2021-04-16 02:36:44 +0000 | [diff] [blame] | 204 | auto& params = GetParam(); |
Antonio Maiorano | 9970ec6 | 2021-03-18 17:59:54 +0000 | [diff] [blame] | 205 | |
| 206 | ast::StructMemberList members{ |
| 207 | Member("a", ty.i32(), |
| 208 | ast::DecorationList{ |
| 209 | createDecoration(Source{{12, 34}}, *this, params.kind)})}; |
| 210 | auto* s = create<ast::Struct>(members, ast::DecorationList{}); |
| 211 | auto* s_ty = ty.struct_("mystruct", s); |
| 212 | AST().AddConstructedType(s_ty); |
| 213 | |
| 214 | WrapInFunction(); |
| 215 | |
| 216 | if (params.should_pass) { |
| 217 | EXPECT_TRUE(r()->Resolve()) << r()->error(); |
| 218 | } else { |
| 219 | EXPECT_FALSE(r()->Resolve()) << r()->error(); |
| 220 | EXPECT_EQ(r()->error(), |
| 221 | "12:34 error: decoration is not valid for structure members"); |
| 222 | } |
| 223 | } |
| 224 | INSTANTIATE_TEST_SUITE_P( |
| 225 | ResolverDecorationValidationTest, |
| 226 | StructMemberDecorationTest, |
| 227 | testing::Values(TestParams{DecorationKind::kAccess, false}, |
| 228 | TestParams{DecorationKind::kAlign, true}, |
| 229 | TestParams{DecorationKind::kBinding, false}, |
| 230 | TestParams{DecorationKind::kBuiltin, true}, |
| 231 | TestParams{DecorationKind::kConstantId, false}, |
| 232 | TestParams{DecorationKind::kGroup, false}, |
| 233 | TestParams{DecorationKind::kLocation, true}, |
| 234 | TestParams{DecorationKind::kOffset, true}, |
| 235 | TestParams{DecorationKind::kSize, true}, |
| 236 | TestParams{DecorationKind::kStage, false}, |
| 237 | TestParams{DecorationKind::kStride, false}, |
| 238 | TestParams{DecorationKind::kStructBlock, false}, |
| 239 | TestParams{DecorationKind::kWorkgroup, false})); |
| 240 | |
Antonio Maiorano | bbbb0ed | 2021-04-06 20:18:57 +0000 | [diff] [blame] | 241 | using VariableDecorationTest = TestWithParams; |
| 242 | TEST_P(VariableDecorationTest, IsValid) { |
Antonio Maiorano | fc03a46 | 2021-04-16 02:36:44 +0000 | [diff] [blame] | 243 | auto& params = GetParam(); |
Antonio Maiorano | bbbb0ed | 2021-04-06 20:18:57 +0000 | [diff] [blame] | 244 | |
| 245 | Global("a", ty.f32(), ast::StorageClass::kInput, nullptr, |
| 246 | ast::DecorationList{ |
| 247 | createDecoration(Source{{12, 34}}, *this, params.kind)}); |
| 248 | |
| 249 | WrapInFunction(); |
| 250 | |
| 251 | if (params.should_pass) { |
| 252 | EXPECT_TRUE(r()->Resolve()) << r()->error(); |
| 253 | } else { |
| 254 | EXPECT_FALSE(r()->Resolve()) << r()->error(); |
| 255 | EXPECT_EQ(r()->error(), |
| 256 | "12:34 error: decoration is not valid for variables"); |
| 257 | } |
| 258 | } |
| 259 | INSTANTIATE_TEST_SUITE_P( |
Antonio Maiorano | d15391e | 2021-04-08 14:08:47 +0000 | [diff] [blame] | 260 | ResolverDecorationValidationTest, |
Antonio Maiorano | bbbb0ed | 2021-04-06 20:18:57 +0000 | [diff] [blame] | 261 | VariableDecorationTest, |
| 262 | testing::Values(TestParams{DecorationKind::kAccess, false}, |
| 263 | TestParams{DecorationKind::kAlign, false}, |
| 264 | TestParams{DecorationKind::kBinding, true}, |
| 265 | TestParams{DecorationKind::kBuiltin, true}, |
| 266 | TestParams{DecorationKind::kConstantId, true}, |
| 267 | TestParams{DecorationKind::kGroup, true}, |
| 268 | TestParams{DecorationKind::kLocation, true}, |
| 269 | TestParams{DecorationKind::kOffset, false}, |
| 270 | TestParams{DecorationKind::kSize, false}, |
| 271 | TestParams{DecorationKind::kStage, false}, |
| 272 | TestParams{DecorationKind::kStride, false}, |
| 273 | TestParams{DecorationKind::kStructBlock, false}, |
| 274 | TestParams{DecorationKind::kWorkgroup, false})); |
| 275 | |
Antonio Maiorano | bfc9794 | 2021-04-06 20:41:07 +0000 | [diff] [blame] | 276 | using FunctionDecorationTest = TestWithParams; |
| 277 | TEST_P(FunctionDecorationTest, IsValid) { |
Antonio Maiorano | fc03a46 | 2021-04-16 02:36:44 +0000 | [diff] [blame] | 278 | auto& params = GetParam(); |
Antonio Maiorano | bfc9794 | 2021-04-06 20:41:07 +0000 | [diff] [blame] | 279 | |
| 280 | Func("foo", ast::VariableList{}, ty.void_(), ast::StatementList{}, |
| 281 | ast::DecorationList{ |
| 282 | create<ast::StageDecoration>(ast::PipelineStage::kCompute), |
| 283 | createDecoration(Source{{12, 34}}, *this, params.kind)}); |
| 284 | |
| 285 | if (params.should_pass) { |
| 286 | EXPECT_TRUE(r()->Resolve()) << r()->error(); |
| 287 | } else { |
| 288 | EXPECT_FALSE(r()->Resolve()) << r()->error(); |
| 289 | EXPECT_EQ(r()->error(), |
| 290 | "12:34 error: decoration is not valid for functions"); |
| 291 | } |
| 292 | } |
| 293 | INSTANTIATE_TEST_SUITE_P( |
Antonio Maiorano | d15391e | 2021-04-08 14:08:47 +0000 | [diff] [blame] | 294 | ResolverDecorationValidationTest, |
Antonio Maiorano | bfc9794 | 2021-04-06 20:41:07 +0000 | [diff] [blame] | 295 | FunctionDecorationTest, |
| 296 | testing::Values(TestParams{DecorationKind::kAccess, false}, |
| 297 | TestParams{DecorationKind::kAlign, false}, |
| 298 | TestParams{DecorationKind::kBinding, false}, |
| 299 | TestParams{DecorationKind::kBuiltin, false}, |
| 300 | TestParams{DecorationKind::kConstantId, false}, |
| 301 | TestParams{DecorationKind::kGroup, false}, |
| 302 | TestParams{DecorationKind::kLocation, false}, |
| 303 | TestParams{DecorationKind::kOffset, false}, |
| 304 | TestParams{DecorationKind::kSize, false}, |
| 305 | // Skip kStage as we always apply it in this test |
| 306 | TestParams{DecorationKind::kStride, false}, |
| 307 | TestParams{DecorationKind::kStructBlock, false}, |
| 308 | TestParams{DecorationKind::kWorkgroup, true})); |
| 309 | |
Antonio Maiorano | 9970ec6 | 2021-03-18 17:59:54 +0000 | [diff] [blame] | 310 | } // namespace |
Antonio Maiorano | fc03a46 | 2021-04-16 02:36:44 +0000 | [diff] [blame] | 311 | } // namespace DecorationTests |
| 312 | |
| 313 | namespace ArrayStrideTests { |
| 314 | namespace { |
| 315 | |
| 316 | struct Params { |
| 317 | create_type_func_ptr create_el_type; |
| 318 | uint32_t stride; |
| 319 | bool should_pass; |
| 320 | }; |
| 321 | |
| 322 | struct TestWithParams : ResolverTestWithParam<Params> {}; |
| 323 | |
| 324 | using ArrayStrideTest = TestWithParams; |
| 325 | TEST_P(ArrayStrideTest, All) { |
| 326 | auto& params = GetParam(); |
| 327 | auto* el_ty = params.create_el_type(ty); |
| 328 | |
| 329 | std::stringstream ss; |
| 330 | ss << "el_ty: " << el_ty->FriendlyName(Symbols()) |
| 331 | << ", stride: " << params.stride |
| 332 | << ", should_pass: " << params.should_pass; |
| 333 | SCOPED_TRACE(ss.str()); |
| 334 | |
| 335 | auto* arr = |
Antonio Maiorano | 3751fd2 | 2021-04-19 22:51:23 +0000 | [diff] [blame^] | 336 | create<sem::ArrayType>(el_ty, 4, |
| 337 | ast::DecorationList{ |
| 338 | create<ast::StrideDecoration>(params.stride), |
| 339 | }); |
Antonio Maiorano | fc03a46 | 2021-04-16 02:36:44 +0000 | [diff] [blame] | 340 | |
| 341 | Global(Source{{12, 34}}, "myarray", arr, ast::StorageClass::kInput); |
| 342 | |
| 343 | if (params.should_pass) { |
| 344 | EXPECT_TRUE(r()->Resolve()) << r()->error(); |
| 345 | } else { |
| 346 | EXPECT_FALSE(r()->Resolve()); |
| 347 | EXPECT_EQ(r()->error(), |
| 348 | "12:34 error: arrays decorated with the stride attribute must " |
| 349 | "have a stride that is at least the size of the element type, " |
| 350 | "and be a multiple of the element type's alignment value."); |
| 351 | } |
| 352 | } |
| 353 | |
| 354 | // Helpers and typedefs |
| 355 | using i32 = ProgramBuilder::i32; |
| 356 | using u32 = ProgramBuilder::u32; |
| 357 | using f32 = ProgramBuilder::f32; |
| 358 | |
| 359 | struct SizeAndAlignment { |
| 360 | uint32_t size; |
| 361 | uint32_t align; |
| 362 | }; |
| 363 | constexpr SizeAndAlignment default_u32 = {4, 4}; |
| 364 | constexpr SizeAndAlignment default_i32 = {4, 4}; |
| 365 | constexpr SizeAndAlignment default_f32 = {4, 4}; |
| 366 | constexpr SizeAndAlignment default_vec2 = {8, 8}; |
| 367 | constexpr SizeAndAlignment default_vec3 = {12, 16}; |
| 368 | constexpr SizeAndAlignment default_vec4 = {16, 16}; |
| 369 | constexpr SizeAndAlignment default_mat2x2 = {16, 8}; |
| 370 | constexpr SizeAndAlignment default_mat3x3 = {48, 16}; |
| 371 | constexpr SizeAndAlignment default_mat4x4 = {64, 16}; |
| 372 | |
| 373 | INSTANTIATE_TEST_SUITE_P( |
| 374 | ResolverDecorationValidationTest, |
| 375 | ArrayStrideTest, |
| 376 | testing::Values( |
| 377 | // Succeed because stride >= element size (while being multiple of |
| 378 | // element alignment) |
| 379 | Params{ty_u32, default_u32.size, true}, |
| 380 | Params{ty_i32, default_i32.size, true}, |
| 381 | Params{ty_f32, default_f32.size, true}, |
| 382 | Params{ty_vec2<f32>, default_vec2.size, true}, |
| 383 | // vec3's default size is not a multiple of its alignment |
| 384 | // Params{ty_vec3<f32>, default_vec3.size, true}, |
| 385 | Params{ty_vec4<f32>, default_vec4.size, true}, |
| 386 | Params{ty_mat2x2<f32>, default_mat2x2.size, true}, |
| 387 | Params{ty_mat3x3<f32>, default_mat3x3.size, true}, |
| 388 | Params{ty_mat4x4<f32>, default_mat4x4.size, true}, |
| 389 | |
| 390 | // Fail because stride is < element size |
| 391 | Params{ty_u32, default_u32.size - 1, false}, |
| 392 | Params{ty_i32, default_i32.size - 1, false}, |
| 393 | Params{ty_f32, default_f32.size - 1, false}, |
| 394 | Params{ty_vec2<f32>, default_vec2.size - 1, false}, |
| 395 | Params{ty_vec3<f32>, default_vec3.size - 1, false}, |
| 396 | Params{ty_vec4<f32>, default_vec4.size - 1, false}, |
| 397 | Params{ty_mat2x2<f32>, default_mat2x2.size - 1, false}, |
| 398 | Params{ty_mat3x3<f32>, default_mat3x3.size - 1, false}, |
| 399 | Params{ty_mat4x4<f32>, default_mat4x4.size - 1, false}, |
| 400 | |
| 401 | // Succeed because stride equals multiple of element alignment |
| 402 | Params{ty_u32, default_u32.align * 7, true}, |
| 403 | Params{ty_i32, default_i32.align * 7, true}, |
| 404 | Params{ty_f32, default_f32.align * 7, true}, |
| 405 | Params{ty_vec2<f32>, default_vec2.align * 7, true}, |
| 406 | Params{ty_vec3<f32>, default_vec3.align * 7, true}, |
| 407 | Params{ty_vec4<f32>, default_vec4.align * 7, true}, |
| 408 | Params{ty_mat2x2<f32>, default_mat2x2.align * 7, true}, |
| 409 | Params{ty_mat3x3<f32>, default_mat3x3.align * 7, true}, |
| 410 | Params{ty_mat4x4<f32>, default_mat4x4.align * 7, true}, |
| 411 | |
| 412 | // Fail because stride is not multiple of element alignment |
| 413 | Params{ty_u32, (default_u32.align - 1) * 7, false}, |
| 414 | Params{ty_i32, (default_i32.align - 1) * 7, false}, |
| 415 | Params{ty_f32, (default_f32.align - 1) * 7, false}, |
| 416 | Params{ty_vec2<f32>, (default_vec2.align - 1) * 7, false}, |
| 417 | Params{ty_vec3<f32>, (default_vec3.align - 1) * 7, false}, |
| 418 | Params{ty_vec4<f32>, (default_vec4.align - 1) * 7, false}, |
| 419 | Params{ty_mat2x2<f32>, (default_mat2x2.align - 1) * 7, false}, |
| 420 | Params{ty_mat3x3<f32>, (default_mat3x3.align - 1) * 7, false}, |
Ben Clayton | 648b05e | 2021-04-16 10:37:34 +0000 | [diff] [blame] | 421 | Params{ty_mat4x4<f32>, (default_mat4x4.align - 1) * 7, false})); |
Antonio Maiorano | fc03a46 | 2021-04-16 02:36:44 +0000 | [diff] [blame] | 422 | |
Ben Clayton | 6fcefe4 | 2021-04-19 19:16:12 +0000 | [diff] [blame] | 423 | TEST_F(ArrayStrideTest, MultipleDecorations) { |
Antonio Maiorano | 3751fd2 | 2021-04-19 22:51:23 +0000 | [diff] [blame^] | 424 | auto* arr = create<sem::ArrayType>(ty.i32(), 4, |
| 425 | ast::DecorationList{ |
| 426 | create<ast::StrideDecoration>(4), |
| 427 | create<ast::StrideDecoration>(4), |
| 428 | }); |
Ben Clayton | 6fcefe4 | 2021-04-19 19:16:12 +0000 | [diff] [blame] | 429 | |
| 430 | Global(Source{{12, 34}}, "myarray", arr, ast::StorageClass::kInput); |
| 431 | |
| 432 | EXPECT_FALSE(r()->Resolve()); |
| 433 | EXPECT_EQ(r()->error(), |
| 434 | "12:34 error: array must have at most one [[stride]] decoration"); |
| 435 | } |
| 436 | |
Antonio Maiorano | fc03a46 | 2021-04-16 02:36:44 +0000 | [diff] [blame] | 437 | } // namespace |
| 438 | } // namespace ArrayStrideTests |
| 439 | } // namespace resolver |
Antonio Maiorano | 9970ec6 | 2021-03-18 17:59:54 +0000 | [diff] [blame] | 440 | } // namespace tint |