Austin Eng | cc2516a | 2023-10-17 20:57:54 +0000 | [diff] [blame] | 1 | // Copyright 2021 The Dawn & Tint Authors |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 2 | // |
Austin Eng | cc2516a | 2023-10-17 20:57:54 +0000 | [diff] [blame] | 3 | // Redistribution and use in source and binary forms, with or without |
| 4 | // modification, are permitted provided that the following conditions are met: |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 5 | // |
Austin Eng | cc2516a | 2023-10-17 20:57:54 +0000 | [diff] [blame] | 6 | // 1. Redistributions of source code must retain the above copyright notice, this |
| 7 | // list of conditions and the following disclaimer. |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 8 | // |
Austin Eng | cc2516a | 2023-10-17 20:57:54 +0000 | [diff] [blame] | 9 | // 2. Redistributions in binary form must reproduce the above copyright notice, |
| 10 | // this list of conditions and the following disclaimer in the documentation |
| 11 | // and/or other materials provided with the distribution. |
| 12 | // |
| 13 | // 3. Neither the name of the copyright holder nor the names of its |
| 14 | // contributors may be used to endorse or promote products derived from |
| 15 | // this software without specific prior written permission. |
| 16 | // |
| 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| 18 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 19 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| 20 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
| 21 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 22 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| 24 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| 25 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 27 | |
Ben Clayton | cd52f38 | 2023-08-07 13:11:08 +0000 | [diff] [blame] | 28 | #include "src/tint/lang/core/builtin_value.h" |
dan sinclair | 99181d8 | 2023-07-20 01:14:15 +0000 | [diff] [blame] | 29 | #include "src/tint/lang/wgsl/ast/builtin_attribute.h" |
| 30 | #include "src/tint/lang/wgsl/ast/location_attribute.h" |
| 31 | #include "src/tint/lang/wgsl/ast/return_statement.h" |
| 32 | #include "src/tint/lang/wgsl/ast/stage_attribute.h" |
dan sinclair | 9d97f22 | 2023-07-24 17:11:53 +0000 | [diff] [blame] | 33 | #include "src/tint/lang/wgsl/resolver/resolver.h" |
Ben Clayton | d368f2c | 2023-08-01 00:37:35 +0000 | [diff] [blame] | 34 | #include "src/tint/lang/wgsl/resolver/resolver_helper_test.h" |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 35 | |
| 36 | #include "gmock/gmock.h" |
| 37 | |
dan sinclair | d209379 | 2022-04-07 17:45:45 +0000 | [diff] [blame] | 38 | namespace tint::resolver { |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 39 | namespace { |
| 40 | |
Ben Clayton | a87e5d6 | 2023-08-15 14:56:16 +0000 | [diff] [blame] | 41 | using namespace tint::core::fluent_types; // NOLINT |
dan sinclair | ce6dffe | 2023-08-14 21:01:40 +0000 | [diff] [blame] | 42 | using namespace tint::core::number_suffixes; // NOLINT |
Ben Clayton | 66805b0 | 2023-06-14 22:00:01 +0000 | [diff] [blame] | 43 | |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 44 | // Helpers and typedefs |
| 45 | template <typename T> |
| 46 | using DataType = builder::DataType<T>; |
| 47 | template <typename T> |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 48 | using alias = builder::alias<T>; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 49 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 50 | class ResolverEntryPointValidationTest : public TestHelper, public testing::Test {}; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 51 | |
| 52 | TEST_F(ResolverEntryPointValidationTest, ReturnTypeAttribute_Location) { |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 53 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 54 | // fn main() -> @location(0) f32 { return 1.0; } |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 55 | Func(Source{{12, 34}}, "main", tint::Empty, ty.f32(), |
| 56 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 57 | Return(1_f), |
| 58 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 59 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 60 | Stage(ast::PipelineStage::kFragment), |
| 61 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 62 | Vector{ |
dan sinclair | f9eeed6 | 2022-09-07 22:25:24 +0000 | [diff] [blame] | 63 | Location(0_a), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 64 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 65 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 66 | EXPECT_TRUE(r()->Resolve()) << r()->error(); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 67 | } |
| 68 | |
| 69 | TEST_F(ResolverEntryPointValidationTest, ReturnTypeAttribute_Builtin) { |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 70 | // @vertex |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 71 | // fn main() -> @builtin(position) vec4<f32> { return vec4<f32>(); } |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 72 | Func(Source{{12, 34}}, "main", tint::Empty, ty.vec4<f32>(), |
| 73 | Vector{ |
Ben Clayton | 66805b0 | 2023-06-14 22:00:01 +0000 | [diff] [blame] | 74 | Return(Call<vec4<f32>>()), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 75 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 76 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 77 | Stage(ast::PipelineStage::kVertex), |
| 78 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 79 | Vector{ |
Ben Clayton | cd52f38 | 2023-08-07 13:11:08 +0000 | [diff] [blame] | 80 | Builtin(core::BuiltinValue::kPosition), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 81 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 82 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 83 | EXPECT_TRUE(r()->Resolve()) << r()->error(); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 84 | } |
| 85 | |
| 86 | TEST_F(ResolverEntryPointValidationTest, ReturnTypeAttribute_Missing) { |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 87 | // @vertex |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 88 | // fn main() -> f32 { |
| 89 | // return 1.0; |
| 90 | // } |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 91 | Func(Source{{12, 34}}, "main", tint::Empty, ty.vec4<f32>(), |
| 92 | Vector{ |
Ben Clayton | 66805b0 | 2023-06-14 22:00:01 +0000 | [diff] [blame] | 93 | Return(Call<vec4<f32>>()), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 94 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 95 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 96 | Stage(ast::PipelineStage::kVertex), |
| 97 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 98 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 99 | EXPECT_FALSE(r()->Resolve()); |
Ben Clayton | 4d3ff97 | 2023-02-21 17:33:54 +0000 | [diff] [blame] | 100 | EXPECT_EQ(r()->error(), R"(12:34 error: missing entry point IO attribute on return type)"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 101 | } |
| 102 | |
| 103 | TEST_F(ResolverEntryPointValidationTest, ReturnTypeAttribute_Multiple) { |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 104 | // @vertex |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 105 | // fn main() -> @location(0) @builtin(position) vec4<f32> { |
| 106 | // return vec4<f32>(); |
| 107 | // } |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 108 | Func(Source{{12, 34}}, "main", tint::Empty, ty.vec4<f32>(), |
| 109 | Vector{ |
Ben Clayton | 66805b0 | 2023-06-14 22:00:01 +0000 | [diff] [blame] | 110 | Return(Call<vec4<f32>>()), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 111 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 112 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 113 | Stage(ast::PipelineStage::kVertex), |
| 114 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 115 | Vector{ |
dan sinclair | f9eeed6 | 2022-09-07 22:25:24 +0000 | [diff] [blame] | 116 | Location(Source{{13, 43}}, 0_a), |
Ben Clayton | cd52f38 | 2023-08-07 13:11:08 +0000 | [diff] [blame] | 117 | Builtin(Source{{14, 52}}, core::BuiltinValue::kPosition), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 118 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 119 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 120 | EXPECT_FALSE(r()->Resolve()); |
| 121 | EXPECT_EQ(r()->error(), R"(14:52 error: multiple entry point IO attributes |
Ben Clayton | 710b62f | 2024-02-26 20:24:06 +0000 | [diff] [blame] | 122 | 13:43 note: previously consumed '@location')"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 123 | } |
| 124 | |
| 125 | TEST_F(ResolverEntryPointValidationTest, ReturnType_Struct_Valid) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 126 | // struct Output { |
| 127 | // @location(0) a : f32; |
| 128 | // @builtin(frag_depth) b : f32; |
| 129 | // }; |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 130 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 131 | // fn main() -> Output { |
| 132 | // return Output(); |
| 133 | // } |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 134 | auto* output = Structure( |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 135 | "Output", Vector{ |
| 136 | Member("a", ty.f32(), Vector{Location(0_a)}), |
Ben Clayton | cd52f38 | 2023-08-07 13:11:08 +0000 | [diff] [blame] | 137 | Member("b", ty.f32(), Vector{Builtin(core::BuiltinValue::kFragDepth)}), |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 138 | }); |
| 139 | Func(Source{{12, 34}}, "main", tint::Empty, ty.Of(output), |
| 140 | Vector{ |
Ben Clayton | 01ac21c | 2023-02-07 16:14:25 +0000 | [diff] [blame] | 141 | Return(Call(ty.Of(output))), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 142 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 143 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 144 | Stage(ast::PipelineStage::kFragment), |
| 145 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 146 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 147 | EXPECT_TRUE(r()->Resolve()) << r()->error(); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 148 | } |
| 149 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 150 | TEST_F(ResolverEntryPointValidationTest, ReturnType_Struct_MemberMultipleAttributes) { |
| 151 | // struct Output { |
| 152 | // @location(0) @builtin(frag_depth) a : f32; |
| 153 | // }; |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 154 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 155 | // fn main() -> Output { |
| 156 | // return Output(); |
| 157 | // } |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 158 | auto* output = Structure( |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 159 | "Output", Vector{ |
| 160 | Member("a", ty.f32(), |
| 161 | Vector{Location(Source{{13, 43}}, 0_a), |
Ben Clayton | cd52f38 | 2023-08-07 13:11:08 +0000 | [diff] [blame] | 162 | Builtin(Source{{14, 52}}, core::BuiltinValue::kFragDepth)}), |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 163 | }); |
| 164 | Func(Source{{12, 34}}, "main", tint::Empty, ty.Of(output), |
| 165 | Vector{ |
Ben Clayton | 01ac21c | 2023-02-07 16:14:25 +0000 | [diff] [blame] | 166 | Return(Call(ty.Of(output))), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 167 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 168 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 169 | Stage(ast::PipelineStage::kFragment), |
| 170 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 171 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 172 | EXPECT_FALSE(r()->Resolve()); |
| 173 | EXPECT_EQ(r()->error(), R"(14:52 error: multiple entry point IO attributes |
Ben Clayton | 710b62f | 2024-02-26 20:24:06 +0000 | [diff] [blame] | 174 | 13:43 note: previously consumed '@location' |
Ben Clayton | 4fe330f | 2022-10-13 13:33:25 +0000 | [diff] [blame] | 175 | 12:34 note: while analyzing entry point 'main')"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 176 | } |
| 177 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 178 | TEST_F(ResolverEntryPointValidationTest, ReturnType_Struct_MemberMissingAttribute) { |
| 179 | // struct Output { |
| 180 | // @location(0) a : f32; |
| 181 | // b : f32; |
| 182 | // }; |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 183 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 184 | // fn main() -> Output { |
| 185 | // return Output(); |
| 186 | // } |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 187 | auto* output = |
| 188 | Structure("Output", Vector{ |
| 189 | Member(Source{{13, 43}}, "a", ty.f32(), Vector{Location(0_a)}), |
| 190 | Member(Source{{14, 52}}, "b", ty.f32(), {}), |
| 191 | }); |
| 192 | Func(Source{{12, 34}}, "main", tint::Empty, ty.Of(output), |
| 193 | Vector{ |
Ben Clayton | 01ac21c | 2023-02-07 16:14:25 +0000 | [diff] [blame] | 194 | Return(Call(ty.Of(output))), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 195 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 196 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 197 | Stage(ast::PipelineStage::kFragment), |
| 198 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 199 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 200 | EXPECT_FALSE(r()->Resolve()); |
| 201 | EXPECT_EQ(r()->error(), |
| 202 | R"(14:52 error: missing entry point IO attribute |
Ben Clayton | 4fe330f | 2022-10-13 13:33:25 +0000 | [diff] [blame] | 203 | 12:34 note: while analyzing entry point 'main')"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 204 | } |
| 205 | |
| 206 | TEST_F(ResolverEntryPointValidationTest, ReturnType_Struct_DuplicateBuiltins) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 207 | // struct Output { |
| 208 | // @builtin(frag_depth) a : f32; |
| 209 | // @builtin(frag_depth) b : f32; |
| 210 | // }; |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 211 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 212 | // fn main() -> Output { |
| 213 | // return Output(); |
| 214 | // } |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 215 | auto* output = Structure( |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 216 | "Output", Vector{ |
Ben Clayton | cd52f38 | 2023-08-07 13:11:08 +0000 | [diff] [blame] | 217 | Member("a", ty.f32(), Vector{Builtin(core::BuiltinValue::kFragDepth)}), |
| 218 | Member("b", ty.f32(), Vector{Builtin(core::BuiltinValue::kFragDepth)}), |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 219 | }); |
| 220 | Func(Source{{12, 34}}, "main", tint::Empty, ty.Of(output), |
| 221 | Vector{ |
Ben Clayton | 01ac21c | 2023-02-07 16:14:25 +0000 | [diff] [blame] | 222 | Return(Call(ty.Of(output))), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 223 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 224 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 225 | Stage(ast::PipelineStage::kFragment), |
| 226 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 227 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 228 | EXPECT_FALSE(r()->Resolve()); |
Ben Clayton | 4d3ff97 | 2023-02-21 17:33:54 +0000 | [diff] [blame] | 229 | EXPECT_EQ(r()->error(), |
Ben Clayton | 710b62f | 2024-02-26 20:24:06 +0000 | [diff] [blame] | 230 | R"(12:34 error: '@builtin(frag_depth)' appears multiple times as pipeline output |
Ben Clayton | 4fe330f | 2022-10-13 13:33:25 +0000 | [diff] [blame] | 231 | 12:34 note: while analyzing entry point 'main')"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 232 | } |
| 233 | |
| 234 | TEST_F(ResolverEntryPointValidationTest, ParameterAttribute_Location) { |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 235 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 236 | // fn main(@location(0) param : f32) {} |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 237 | auto* param = Param("param", ty.f32(), |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 238 | Vector{ |
dan sinclair | f9eeed6 | 2022-09-07 22:25:24 +0000 | [diff] [blame] | 239 | Location(0_a), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 240 | }); |
| 241 | Func(Source{{12, 34}}, "main", |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 242 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 243 | param, |
| 244 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 245 | ty.void_(), tint::Empty, |
| 246 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 247 | Stage(ast::PipelineStage::kFragment), |
| 248 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 249 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 250 | EXPECT_TRUE(r()->Resolve()) << r()->error(); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 251 | } |
| 252 | |
| 253 | TEST_F(ResolverEntryPointValidationTest, ParameterAttribute_Missing) { |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 254 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 255 | // fn main(param : f32) {} |
| 256 | auto* param = Param(Source{{13, 43}}, "param", ty.vec4<f32>()); |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 257 | Func(Source{{12, 34}}, "main", |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 258 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 259 | param, |
| 260 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 261 | ty.void_(), tint::Empty, |
| 262 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 263 | Stage(ast::PipelineStage::kFragment), |
| 264 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 265 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 266 | EXPECT_FALSE(r()->Resolve()); |
Ben Clayton | 4d3ff97 | 2023-02-21 17:33:54 +0000 | [diff] [blame] | 267 | EXPECT_EQ(r()->error(), R"(13:43 error: missing entry point IO attribute on parameter)"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 268 | } |
| 269 | |
| 270 | TEST_F(ResolverEntryPointValidationTest, ParameterAttribute_Multiple) { |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 271 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 272 | // fn main(@location(0) @builtin(sample_index) param : u32) {} |
Ben Clayton | f330229 | 2022-07-27 18:48:06 +0000 | [diff] [blame] | 273 | auto* param = Param("param", ty.u32(), |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 274 | Vector{ |
dan sinclair | f9eeed6 | 2022-09-07 22:25:24 +0000 | [diff] [blame] | 275 | Location(Source{{13, 43}}, 0_a), |
Ben Clayton | cd52f38 | 2023-08-07 13:11:08 +0000 | [diff] [blame] | 276 | Builtin(Source{{14, 52}}, core::BuiltinValue::kSampleIndex), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 277 | }); |
| 278 | Func(Source{{12, 34}}, "main", |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 279 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 280 | param, |
| 281 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 282 | ty.void_(), tint::Empty, |
| 283 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 284 | Stage(ast::PipelineStage::kFragment), |
| 285 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 286 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 287 | EXPECT_FALSE(r()->Resolve()); |
| 288 | EXPECT_EQ(r()->error(), R"(14:52 error: multiple entry point IO attributes |
Ben Clayton | 710b62f | 2024-02-26 20:24:06 +0000 | [diff] [blame] | 289 | 13:43 note: previously consumed '@location')"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 290 | } |
| 291 | |
| 292 | TEST_F(ResolverEntryPointValidationTest, Parameter_Struct_Valid) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 293 | // struct Input { |
| 294 | // @location(0) a : f32; |
| 295 | // @builtin(sample_index) b : u32; |
| 296 | // }; |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 297 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 298 | // fn main(param : Input) {} |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 299 | auto* input = Structure( |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 300 | "Input", Vector{ |
| 301 | Member("a", ty.f32(), Vector{Location(0_a)}), |
Ben Clayton | cd52f38 | 2023-08-07 13:11:08 +0000 | [diff] [blame] | 302 | Member("b", ty.u32(), Vector{Builtin(core::BuiltinValue::kSampleIndex)}), |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 303 | }); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 304 | auto* param = Param("param", ty.Of(input)); |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 305 | Func(Source{{12, 34}}, "main", |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 306 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 307 | param, |
| 308 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 309 | ty.void_(), tint::Empty, |
| 310 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 311 | Stage(ast::PipelineStage::kFragment), |
| 312 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 313 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 314 | EXPECT_TRUE(r()->Resolve()) << r()->error(); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 315 | } |
| 316 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 317 | TEST_F(ResolverEntryPointValidationTest, Parameter_Struct_MemberMultipleAttributes) { |
| 318 | // struct Input { |
| 319 | // @location(0) @builtin(sample_index) a : u32; |
| 320 | // }; |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 321 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 322 | // fn main(param : Input) {} |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 323 | auto* input = Structure( |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 324 | "Input", Vector{ |
| 325 | Member("a", ty.u32(), |
| 326 | Vector{Location(Source{{13, 43}}, 0_a), |
Ben Clayton | cd52f38 | 2023-08-07 13:11:08 +0000 | [diff] [blame] | 327 | Builtin(Source{{14, 52}}, core::BuiltinValue::kSampleIndex)}), |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 328 | }); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 329 | auto* param = Param("param", ty.Of(input)); |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 330 | Func(Source{{12, 34}}, "main", |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 331 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 332 | param, |
| 333 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 334 | ty.void_(), tint::Empty, |
| 335 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 336 | Stage(ast::PipelineStage::kFragment), |
| 337 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 338 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 339 | EXPECT_FALSE(r()->Resolve()); |
| 340 | EXPECT_EQ(r()->error(), R"(14:52 error: multiple entry point IO attributes |
Ben Clayton | 710b62f | 2024-02-26 20:24:06 +0000 | [diff] [blame] | 341 | 13:43 note: previously consumed '@location' |
Ben Clayton | 4fe330f | 2022-10-13 13:33:25 +0000 | [diff] [blame] | 342 | 12:34 note: while analyzing entry point 'main')"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 343 | } |
| 344 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 345 | TEST_F(ResolverEntryPointValidationTest, Parameter_Struct_MemberMissingAttribute) { |
| 346 | // struct Input { |
| 347 | // @location(0) a : f32; |
| 348 | // b : f32; |
| 349 | // }; |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 350 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 351 | // fn main(param : Input) {} |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 352 | auto* input = |
| 353 | Structure("Input", Vector{ |
| 354 | Member(Source{{13, 43}}, "a", ty.f32(), Vector{Location(0_a)}), |
| 355 | Member(Source{{14, 52}}, "b", ty.f32(), {}), |
| 356 | }); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 357 | auto* param = Param("param", ty.Of(input)); |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 358 | Func(Source{{12, 34}}, "main", |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 359 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 360 | param, |
| 361 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 362 | ty.void_(), tint::Empty, |
| 363 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 364 | Stage(ast::PipelineStage::kFragment), |
| 365 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 366 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 367 | EXPECT_FALSE(r()->Resolve()); |
| 368 | EXPECT_EQ(r()->error(), R"(14:52 error: missing entry point IO attribute |
Ben Clayton | 4fe330f | 2022-10-13 13:33:25 +0000 | [diff] [blame] | 369 | 12:34 note: while analyzing entry point 'main')"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 370 | } |
| 371 | |
| 372 | TEST_F(ResolverEntryPointValidationTest, Parameter_DuplicateBuiltins) { |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 373 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 374 | // fn main(@builtin(sample_index) param_a : u32, |
| 375 | // @builtin(sample_index) param_b : u32) {} |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 376 | auto* param_a = Param("param_a", ty.u32(), |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 377 | Vector{ |
Ben Clayton | cd52f38 | 2023-08-07 13:11:08 +0000 | [diff] [blame] | 378 | Builtin(core::BuiltinValue::kSampleIndex), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 379 | }); |
| 380 | auto* param_b = Param("param_b", ty.u32(), |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 381 | Vector{ |
Ben Clayton | cd52f38 | 2023-08-07 13:11:08 +0000 | [diff] [blame] | 382 | Builtin(core::BuiltinValue::kSampleIndex), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 383 | }); |
| 384 | Func(Source{{12, 34}}, "main", |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 385 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 386 | param_a, |
| 387 | param_b, |
| 388 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 389 | ty.void_(), tint::Empty, |
| 390 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 391 | Stage(ast::PipelineStage::kFragment), |
| 392 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 393 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 394 | EXPECT_FALSE(r()->Resolve()); |
| 395 | EXPECT_EQ(r()->error(), |
Ben Clayton | 710b62f | 2024-02-26 20:24:06 +0000 | [diff] [blame] | 396 | "12:34 error: '@builtin(sample_index)' appears multiple times as pipeline input"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 397 | } |
| 398 | |
| 399 | TEST_F(ResolverEntryPointValidationTest, Parameter_Struct_DuplicateBuiltins) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 400 | // struct InputA { |
| 401 | // @builtin(sample_index) a : u32; |
| 402 | // }; |
| 403 | // struct InputB { |
| 404 | // @builtin(sample_index) a : u32; |
| 405 | // }; |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 406 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 407 | // fn main(param_a : InputA, param_b : InputB) {} |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 408 | auto* input_a = Structure( |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 409 | "InputA", Vector{ |
Ben Clayton | cd52f38 | 2023-08-07 13:11:08 +0000 | [diff] [blame] | 410 | Member("a", ty.u32(), Vector{Builtin(core::BuiltinValue::kSampleIndex)}), |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 411 | }); |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 412 | auto* input_b = Structure( |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 413 | "InputB", Vector{ |
Ben Clayton | cd52f38 | 2023-08-07 13:11:08 +0000 | [diff] [blame] | 414 | Member("a", ty.u32(), Vector{Builtin(core::BuiltinValue::kSampleIndex)}), |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 415 | }); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 416 | auto* param_a = Param("param_a", ty.Of(input_a)); |
| 417 | auto* param_b = Param("param_b", ty.Of(input_b)); |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 418 | Func(Source{{12, 34}}, "main", |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 419 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 420 | param_a, |
| 421 | param_b, |
| 422 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 423 | ty.void_(), tint::Empty, |
| 424 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 425 | Stage(ast::PipelineStage::kFragment), |
| 426 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 427 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 428 | EXPECT_FALSE(r()->Resolve()); |
Ben Clayton | 4d3ff97 | 2023-02-21 17:33:54 +0000 | [diff] [blame] | 429 | EXPECT_EQ(r()->error(), |
Ben Clayton | 710b62f | 2024-02-26 20:24:06 +0000 | [diff] [blame] | 430 | R"(12:34 error: '@builtin(sample_index)' appears multiple times as pipeline input |
Ben Clayton | 4fe330f | 2022-10-13 13:33:25 +0000 | [diff] [blame] | 431 | 12:34 note: while analyzing entry point 'main')"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 432 | } |
| 433 | |
| 434 | TEST_F(ResolverEntryPointValidationTest, VertexShaderMustReturnPosition) { |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 435 | // @vertex |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 436 | // fn main() {} |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 437 | Func(Source{{12, 34}}, "main", tint::Empty, ty.void_(), tint::Empty, |
| 438 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 439 | Stage(ast::PipelineStage::kVertex), |
| 440 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 441 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 442 | EXPECT_FALSE(r()->Resolve()); |
| 443 | EXPECT_EQ(r()->error(), |
| 444 | "12:34 error: a vertex shader must include the 'position' builtin " |
| 445 | "in its return type"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 446 | } |
| 447 | |
dan sinclair | 4abf28e | 2022-08-02 15:55:35 +0000 | [diff] [blame] | 448 | TEST_F(ResolverEntryPointValidationTest, PushConstantAllowedWithEnable) { |
| 449 | // enable chromium_experimental_push_constant; |
| 450 | // var<push_constant> a : u32; |
Ben Clayton | 1165389 | 2023-09-19 19:15:59 +0000 | [diff] [blame] | 451 | Enable(wgsl::Extension::kChromiumExperimentalPushConstant); |
Ben Clayton | cd52f38 | 2023-08-07 13:11:08 +0000 | [diff] [blame] | 452 | GlobalVar("a", ty.u32(), core::AddressSpace::kPushConstant); |
dan sinclair | 4abf28e | 2022-08-02 15:55:35 +0000 | [diff] [blame] | 453 | |
| 454 | EXPECT_TRUE(r()->Resolve()); |
| 455 | } |
| 456 | |
| 457 | TEST_F(ResolverEntryPointValidationTest, PushConstantDisallowedWithoutEnable) { |
| 458 | // var<push_constant> a : u32; |
Ben Clayton | cd52f38 | 2023-08-07 13:11:08 +0000 | [diff] [blame] | 459 | GlobalVar(Source{{1, 2}}, "a", ty.u32(), core::AddressSpace::kPushConstant); |
dan sinclair | 4abf28e | 2022-08-02 15:55:35 +0000 | [diff] [blame] | 460 | |
| 461 | EXPECT_FALSE(r()->Resolve()); |
| 462 | EXPECT_EQ(r()->error(), |
dan sinclair | ff7cf21 | 2022-10-03 14:05:23 +0000 | [diff] [blame] | 463 | "1:2 error: use of variable address space 'push_constant' requires enabling " |
dan sinclair | 4abf28e | 2022-08-02 15:55:35 +0000 | [diff] [blame] | 464 | "extension 'chromium_experimental_push_constant'"); |
| 465 | } |
| 466 | |
dan sinclair | ff7cf21 | 2022-10-03 14:05:23 +0000 | [diff] [blame] | 467 | TEST_F(ResolverEntryPointValidationTest, PushConstantAllowedWithIgnoreAddressSpaceAttribute) { |
| 468 | // var<push_constant> a : u32; // With ast::DisabledValidation::kIgnoreAddressSpace |
Ben Clayton | cd52f38 | 2023-08-07 13:11:08 +0000 | [diff] [blame] | 469 | GlobalVar("a", ty.u32(), core::AddressSpace::kPushConstant, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 470 | Vector{Disable(ast::DisabledValidation::kIgnoreAddressSpace)}); |
dan sinclair | 4abf28e | 2022-08-02 15:55:35 +0000 | [diff] [blame] | 471 | |
| 472 | EXPECT_TRUE(r()->Resolve()); |
| 473 | } |
| 474 | |
| 475 | TEST_F(ResolverEntryPointValidationTest, PushConstantOneVariableUsedInEntryPoint) { |
| 476 | // enable chromium_experimental_push_constant; |
| 477 | // var<push_constant> a : u32; |
| 478 | // @compute @workgroup_size(1) fn main() { |
| 479 | // _ = a; |
| 480 | // } |
Ben Clayton | 1165389 | 2023-09-19 19:15:59 +0000 | [diff] [blame] | 481 | Enable(wgsl::Extension::kChromiumExperimentalPushConstant); |
Ben Clayton | cd52f38 | 2023-08-07 13:11:08 +0000 | [diff] [blame] | 482 | GlobalVar("a", ty.u32(), core::AddressSpace::kPushConstant); |
dan sinclair | 4abf28e | 2022-08-02 15:55:35 +0000 | [diff] [blame] | 483 | |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 484 | Func("main", {}, ty.void_(), Vector{Assign(Phony(), "a")}, |
Ben Clayton | 4e800c4 | 2023-09-11 16:50:59 +0000 | [diff] [blame] | 485 | Vector{Stage(ast::PipelineStage::kCompute), WorkgroupSize(1_a)}); |
dan sinclair | 4abf28e | 2022-08-02 15:55:35 +0000 | [diff] [blame] | 486 | |
| 487 | EXPECT_TRUE(r()->Resolve()); |
| 488 | } |
| 489 | |
| 490 | TEST_F(ResolverEntryPointValidationTest, PushConstantTwoVariablesUsedInEntryPoint) { |
| 491 | // enable chromium_experimental_push_constant; |
| 492 | // var<push_constant> a : u32; |
| 493 | // var<push_constant> b : u32; |
| 494 | // @compute @workgroup_size(1) fn main() { |
| 495 | // _ = a; |
| 496 | // _ = b; |
| 497 | // } |
Ben Clayton | 1165389 | 2023-09-19 19:15:59 +0000 | [diff] [blame] | 498 | Enable(wgsl::Extension::kChromiumExperimentalPushConstant); |
Ben Clayton | cd52f38 | 2023-08-07 13:11:08 +0000 | [diff] [blame] | 499 | GlobalVar(Source{{1, 2}}, "a", ty.u32(), core::AddressSpace::kPushConstant); |
| 500 | GlobalVar(Source{{3, 4}}, "b", ty.u32(), core::AddressSpace::kPushConstant); |
dan sinclair | 4abf28e | 2022-08-02 15:55:35 +0000 | [diff] [blame] | 501 | |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 502 | Func(Source{{5, 6}}, "main", {}, ty.void_(), Vector{Assign(Phony(), "a"), Assign(Phony(), "b")}, |
Ben Clayton | 4e800c4 | 2023-09-11 16:50:59 +0000 | [diff] [blame] | 503 | Vector{Stage(ast::PipelineStage::kCompute), WorkgroupSize(1_a)}); |
dan sinclair | 4abf28e | 2022-08-02 15:55:35 +0000 | [diff] [blame] | 504 | |
| 505 | EXPECT_FALSE(r()->Resolve()); |
| 506 | EXPECT_EQ(r()->error(), |
| 507 | R"(5:6 error: entry point 'main' uses two different 'push_constant' variables. |
| 508 | 3:4 note: first 'push_constant' variable declaration is here |
| 509 | 1:2 note: second 'push_constant' variable declaration is here)"); |
| 510 | } |
| 511 | |
| 512 | TEST_F(ResolverEntryPointValidationTest, |
| 513 | PushConstantTwoVariablesUsedInEntryPointWithFunctionGraph) { |
| 514 | // enable chromium_experimental_push_constant; |
| 515 | // var<push_constant> a : u32; |
| 516 | // var<push_constant> b : u32; |
| 517 | // fn uses_a() { |
| 518 | // _ = a; |
| 519 | // } |
| 520 | // fn uses_b() { |
| 521 | // _ = b; |
| 522 | // } |
| 523 | // @compute @workgroup_size(1) fn main() { |
| 524 | // uses_a(); |
| 525 | // uses_b(); |
| 526 | // } |
Ben Clayton | 1165389 | 2023-09-19 19:15:59 +0000 | [diff] [blame] | 527 | Enable(wgsl::Extension::kChromiumExperimentalPushConstant); |
Ben Clayton | cd52f38 | 2023-08-07 13:11:08 +0000 | [diff] [blame] | 528 | GlobalVar(Source{{1, 2}}, "a", ty.u32(), core::AddressSpace::kPushConstant); |
| 529 | GlobalVar(Source{{3, 4}}, "b", ty.u32(), core::AddressSpace::kPushConstant); |
dan sinclair | 4abf28e | 2022-08-02 15:55:35 +0000 | [diff] [blame] | 530 | |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 531 | Func(Source{{5, 6}}, "uses_a", {}, ty.void_(), Vector{Assign(Phony(), "a")}); |
| 532 | Func(Source{{7, 8}}, "uses_b", {}, ty.void_(), Vector{Assign(Phony(), "b")}); |
dan sinclair | 4abf28e | 2022-08-02 15:55:35 +0000 | [diff] [blame] | 533 | |
| 534 | Func(Source{{9, 10}}, "main", {}, ty.void_(), |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 535 | Vector{CallStmt(Call("uses_a")), CallStmt(Call("uses_b"))}, |
Ben Clayton | 4e800c4 | 2023-09-11 16:50:59 +0000 | [diff] [blame] | 536 | Vector{Stage(ast::PipelineStage::kCompute), WorkgroupSize(1_a)}); |
dan sinclair | 4abf28e | 2022-08-02 15:55:35 +0000 | [diff] [blame] | 537 | |
| 538 | EXPECT_FALSE(r()->Resolve()); |
| 539 | EXPECT_EQ(r()->error(), |
| 540 | R"(9:10 error: entry point 'main' uses two different 'push_constant' variables. |
| 541 | 3:4 note: first 'push_constant' variable declaration is here |
| 542 | 7:8 note: called by function 'uses_b' |
| 543 | 9:10 note: called by entry point 'main' |
| 544 | 1:2 note: second 'push_constant' variable declaration is here |
| 545 | 5:6 note: called by function 'uses_a' |
| 546 | 9:10 note: called by entry point 'main')"); |
| 547 | } |
| 548 | |
| 549 | TEST_F(ResolverEntryPointValidationTest, PushConstantTwoVariablesUsedInDifferentEntryPoint) { |
| 550 | // enable chromium_experimental_push_constant; |
| 551 | // var<push_constant> a : u32; |
| 552 | // var<push_constant> b : u32; |
| 553 | // @compute @workgroup_size(1) fn uses_a() { |
| 554 | // _ = a; |
| 555 | // } |
| 556 | // @compute @workgroup_size(1) fn uses_b() { |
| 557 | // _ = a; |
| 558 | // } |
Ben Clayton | 1165389 | 2023-09-19 19:15:59 +0000 | [diff] [blame] | 559 | Enable(wgsl::Extension::kChromiumExperimentalPushConstant); |
Ben Clayton | cd52f38 | 2023-08-07 13:11:08 +0000 | [diff] [blame] | 560 | GlobalVar("a", ty.u32(), core::AddressSpace::kPushConstant); |
| 561 | GlobalVar("b", ty.u32(), core::AddressSpace::kPushConstant); |
dan sinclair | 4abf28e | 2022-08-02 15:55:35 +0000 | [diff] [blame] | 562 | |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 563 | Func("uses_a", {}, ty.void_(), Vector{Assign(Phony(), "a")}, |
Ben Clayton | 4e800c4 | 2023-09-11 16:50:59 +0000 | [diff] [blame] | 564 | Vector{Stage(ast::PipelineStage::kCompute), WorkgroupSize(1_a)}); |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 565 | Func("uses_b", {}, ty.void_(), Vector{Assign(Phony(), "b")}, |
Ben Clayton | 4e800c4 | 2023-09-11 16:50:59 +0000 | [diff] [blame] | 566 | Vector{Stage(ast::PipelineStage::kCompute), WorkgroupSize(1_a)}); |
dan sinclair | 4abf28e | 2022-08-02 15:55:35 +0000 | [diff] [blame] | 567 | |
| 568 | EXPECT_TRUE(r()->Resolve()); |
| 569 | } |
| 570 | |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 571 | namespace TypeValidationTests { |
| 572 | struct Params { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 573 | builder::ast_type_func_ptr create_ast_type; |
| 574 | bool is_valid; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 575 | }; |
| 576 | |
| 577 | template <typename T> |
| 578 | constexpr Params ParamsFor(bool is_valid) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 579 | return Params{DataType<T>::AST, is_valid}; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 580 | } |
| 581 | |
| 582 | using TypeValidationTest = resolver::ResolverTestWithParam<Params>; |
| 583 | |
| 584 | static constexpr Params cases[] = { |
| 585 | ParamsFor<f32>(true), // |
| 586 | ParamsFor<i32>(true), // |
| 587 | ParamsFor<u32>(true), // |
| 588 | ParamsFor<bool>(false), // |
| 589 | ParamsFor<vec2<f32>>(true), // |
| 590 | ParamsFor<vec3<f32>>(true), // |
| 591 | ParamsFor<vec4<f32>>(true), // |
| 592 | ParamsFor<mat2x2<f32>>(false), // |
| 593 | ParamsFor<mat3x3<f32>>(false), // |
| 594 | ParamsFor<mat4x4<f32>>(false), // |
| 595 | ParamsFor<alias<f32>>(true), // |
| 596 | ParamsFor<alias<i32>>(true), // |
| 597 | ParamsFor<alias<u32>>(true), // |
| 598 | ParamsFor<alias<bool>>(false), // |
Zhaoming Jiang | 6198bea | 2022-12-07 04:33:24 +0000 | [diff] [blame] | 599 | ParamsFor<f16>(true), // |
| 600 | ParamsFor<vec2<f16>>(true), // |
| 601 | ParamsFor<vec3<f16>>(true), // |
| 602 | ParamsFor<vec4<f16>>(true), // |
Zhaoming Jiang | 9c71174 | 2022-07-08 19:35:05 +0000 | [diff] [blame] | 603 | ParamsFor<mat2x2<f16>>(false), // |
| 604 | ParamsFor<mat3x3<f16>>(false), // |
| 605 | ParamsFor<mat4x4<f16>>(false), // |
Zhaoming Jiang | 6198bea | 2022-12-07 04:33:24 +0000 | [diff] [blame] | 606 | ParamsFor<alias<f16>>(true), // |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 607 | }; |
| 608 | |
| 609 | TEST_P(TypeValidationTest, BareInputs) { |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 610 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 611 | // fn main(@location(0) @interpolate(flat) a : *) {} |
| 612 | auto params = GetParam(); |
Zhaoming Jiang | 9c71174 | 2022-07-08 19:35:05 +0000 | [diff] [blame] | 613 | |
Ben Clayton | 1165389 | 2023-09-19 19:15:59 +0000 | [diff] [blame] | 614 | Enable(wgsl::Extension::kF16); |
Zhaoming Jiang | 9c71174 | 2022-07-08 19:35:05 +0000 | [diff] [blame] | 615 | |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 616 | auto* a = Param("a", params.create_ast_type(*this), |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 617 | Vector{ |
dan sinclair | f9eeed6 | 2022-09-07 22:25:24 +0000 | [diff] [blame] | 618 | Location(0_a), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 619 | Flat(), |
| 620 | }); |
| 621 | Func(Source{{12, 34}}, "main", |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 622 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 623 | a, |
| 624 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 625 | ty.void_(), tint::Empty, |
| 626 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 627 | Stage(ast::PipelineStage::kFragment), |
| 628 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 629 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 630 | if (params.is_valid) { |
| 631 | EXPECT_TRUE(r()->Resolve()) << r()->error(); |
| 632 | } else { |
| 633 | EXPECT_FALSE(r()->Resolve()); |
| 634 | } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 635 | } |
| 636 | |
| 637 | TEST_P(TypeValidationTest, StructInputs) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 638 | // struct Input { |
| 639 | // @location(0) @interpolate(flat) a : *; |
| 640 | // }; |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 641 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 642 | // fn main(a : Input) {} |
| 643 | auto params = GetParam(); |
Zhaoming Jiang | 9c71174 | 2022-07-08 19:35:05 +0000 | [diff] [blame] | 644 | |
Ben Clayton | 1165389 | 2023-09-19 19:15:59 +0000 | [diff] [blame] | 645 | Enable(wgsl::Extension::kF16); |
Zhaoming Jiang | 9c71174 | 2022-07-08 19:35:05 +0000 | [diff] [blame] | 646 | |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 647 | auto* input = Structure( |
| 648 | "Input", Vector{ |
| 649 | Member("a", params.create_ast_type(*this), Vector{Location(0_a), Flat()}), |
| 650 | }); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 651 | auto* a = Param("a", ty.Of(input), {}); |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 652 | Func(Source{{12, 34}}, "main", |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 653 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 654 | a, |
| 655 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 656 | ty.void_(), tint::Empty, |
| 657 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 658 | Stage(ast::PipelineStage::kFragment), |
| 659 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 660 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 661 | if (params.is_valid) { |
| 662 | EXPECT_TRUE(r()->Resolve()) << r()->error(); |
| 663 | } else { |
| 664 | EXPECT_FALSE(r()->Resolve()); |
| 665 | } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 666 | } |
| 667 | |
| 668 | TEST_P(TypeValidationTest, BareOutputs) { |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 669 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 670 | // fn main() -> @location(0) * { |
| 671 | // return *(); |
| 672 | // } |
| 673 | auto params = GetParam(); |
Zhaoming Jiang | 9c71174 | 2022-07-08 19:35:05 +0000 | [diff] [blame] | 674 | |
Ben Clayton | 1165389 | 2023-09-19 19:15:59 +0000 | [diff] [blame] | 675 | Enable(wgsl::Extension::kF16); |
Zhaoming Jiang | 9c71174 | 2022-07-08 19:35:05 +0000 | [diff] [blame] | 676 | |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 677 | Func(Source{{12, 34}}, "main", tint::Empty, params.create_ast_type(*this), |
| 678 | Vector{ |
Ben Clayton | 01ac21c | 2023-02-07 16:14:25 +0000 | [diff] [blame] | 679 | Return(Call(params.create_ast_type(*this))), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 680 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 681 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 682 | Stage(ast::PipelineStage::kFragment), |
| 683 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 684 | Vector{ |
dan sinclair | f9eeed6 | 2022-09-07 22:25:24 +0000 | [diff] [blame] | 685 | Location(0_a), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 686 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 687 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 688 | if (params.is_valid) { |
| 689 | EXPECT_TRUE(r()->Resolve()) << r()->error(); |
| 690 | } else { |
| 691 | EXPECT_FALSE(r()->Resolve()); |
| 692 | } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 693 | } |
| 694 | |
| 695 | TEST_P(TypeValidationTest, StructOutputs) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 696 | // struct Output { |
| 697 | // @location(0) a : *; |
| 698 | // }; |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 699 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 700 | // fn main() -> Output { |
| 701 | // return Output(); |
| 702 | // } |
| 703 | auto params = GetParam(); |
Zhaoming Jiang | 9c71174 | 2022-07-08 19:35:05 +0000 | [diff] [blame] | 704 | |
Ben Clayton | 1165389 | 2023-09-19 19:15:59 +0000 | [diff] [blame] | 705 | Enable(wgsl::Extension::kF16); |
Zhaoming Jiang | 9c71174 | 2022-07-08 19:35:05 +0000 | [diff] [blame] | 706 | |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 707 | auto* output = |
| 708 | Structure("Output", Vector{ |
| 709 | Member("a", params.create_ast_type(*this), Vector{Location(0_a)}), |
| 710 | }); |
| 711 | Func(Source{{12, 34}}, "main", tint::Empty, ty.Of(output), |
| 712 | Vector{ |
Ben Clayton | 01ac21c | 2023-02-07 16:14:25 +0000 | [diff] [blame] | 713 | Return(Call(ty.Of(output))), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 714 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 715 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 716 | Stage(ast::PipelineStage::kFragment), |
| 717 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 718 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 719 | if (params.is_valid) { |
| 720 | EXPECT_TRUE(r()->Resolve()) << r()->error(); |
| 721 | } else { |
| 722 | EXPECT_FALSE(r()->Resolve()); |
| 723 | } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 724 | } |
| 725 | INSTANTIATE_TEST_SUITE_P(ResolverEntryPointValidationTest, |
| 726 | TypeValidationTest, |
| 727 | testing::ValuesIn(cases)); |
| 728 | |
| 729 | } // namespace TypeValidationTests |
| 730 | |
| 731 | namespace LocationAttributeTests { |
| 732 | namespace { |
| 733 | using LocationAttributeTests = ResolverTest; |
| 734 | |
| 735 | TEST_F(LocationAttributeTests, Pass) { |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 736 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 737 | // fn frag_main(@location(0) @interpolate(flat) a: i32) {} |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 738 | |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 739 | auto* p = Param(Source{{12, 34}}, "a", ty.i32(), |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 740 | Vector{ |
dan sinclair | f9eeed6 | 2022-09-07 22:25:24 +0000 | [diff] [blame] | 741 | Location(0_a), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 742 | Flat(), |
| 743 | }); |
| 744 | Func("frag_main", |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 745 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 746 | p, |
| 747 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 748 | ty.void_(), tint::Empty, |
| 749 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 750 | Stage(ast::PipelineStage::kFragment), |
| 751 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 752 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 753 | EXPECT_TRUE(r()->Resolve()) << r()->error(); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 754 | } |
| 755 | |
| 756 | TEST_F(LocationAttributeTests, BadType_Input_bool) { |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 757 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 758 | // fn frag_main(@location(0) a: bool) {} |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 759 | |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 760 | auto* p = Param(Source{{12, 34}}, "a", ty.bool_(), |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 761 | Vector{ |
dan sinclair | f9eeed6 | 2022-09-07 22:25:24 +0000 | [diff] [blame] | 762 | Location(Source{{34, 56}}, 0_a), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 763 | }); |
| 764 | Func("frag_main", |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 765 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 766 | p, |
| 767 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 768 | ty.void_(), tint::Empty, |
| 769 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 770 | Stage(ast::PipelineStage::kFragment), |
| 771 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 772 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 773 | EXPECT_FALSE(r()->Resolve()); |
| 774 | EXPECT_EQ(r()->error(), |
Ben Clayton | 710b62f | 2024-02-26 20:24:06 +0000 | [diff] [blame] | 775 | R"(12:34 error: cannot apply '@location' to declaration of type 'bool' |
| 776 | 34:56 note: '@location' must only be applied to declarations of numeric scalar or numeric vector type)"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 777 | } |
| 778 | |
| 779 | TEST_F(LocationAttributeTests, BadType_Output_Array) { |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 780 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 781 | // fn frag_main()->@location(0) array<f32, 2> { return array<f32, 2>(); } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 782 | |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 783 | Func(Source{{12, 34}}, "frag_main", tint::Empty, ty.array<f32, 2>(), |
| 784 | Vector{ |
Ben Clayton | 66805b0 | 2023-06-14 22:00:01 +0000 | [diff] [blame] | 785 | Return(Call<array<f32, 2>>()), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 786 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 787 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 788 | Stage(ast::PipelineStage::kFragment), |
| 789 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 790 | Vector{ |
dan sinclair | f9eeed6 | 2022-09-07 22:25:24 +0000 | [diff] [blame] | 791 | Location(Source{{34, 56}}, 0_a), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 792 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 793 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 794 | EXPECT_FALSE(r()->Resolve()); |
| 795 | EXPECT_EQ(r()->error(), |
Ben Clayton | 710b62f | 2024-02-26 20:24:06 +0000 | [diff] [blame] | 796 | R"(12:34 error: cannot apply '@location' to declaration of type 'array<f32, 2>' |
| 797 | 34:56 note: '@location' must only be applied to declarations of numeric scalar or numeric vector type)"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 798 | } |
| 799 | |
| 800 | TEST_F(LocationAttributeTests, BadType_Input_Struct) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 801 | // struct Input { |
| 802 | // a : f32; |
| 803 | // }; |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 804 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 805 | // fn main(@location(0) param : Input) {} |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 806 | auto* input = Structure("Input", Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 807 | Member("a", ty.f32()), |
| 808 | }); |
| 809 | auto* param = Param(Source{{12, 34}}, "param", ty.Of(input), |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 810 | Vector{ |
dan sinclair | f9eeed6 | 2022-09-07 22:25:24 +0000 | [diff] [blame] | 811 | Location(Source{{13, 43}}, 0_a), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 812 | }); |
| 813 | Func(Source{{12, 34}}, "main", |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 814 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 815 | param, |
| 816 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 817 | ty.void_(), tint::Empty, |
| 818 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 819 | Stage(ast::PipelineStage::kFragment), |
| 820 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 821 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 822 | EXPECT_FALSE(r()->Resolve()); |
| 823 | EXPECT_EQ(r()->error(), |
Ben Clayton | 710b62f | 2024-02-26 20:24:06 +0000 | [diff] [blame] | 824 | R"(12:34 error: cannot apply '@location' to declaration of type 'Input' |
| 825 | 13:43 note: '@location' must only be applied to declarations of numeric scalar or numeric vector type)"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 826 | } |
| 827 | |
| 828 | TEST_F(LocationAttributeTests, BadType_Input_Struct_NestedStruct) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 829 | // struct Inner { |
| 830 | // @location(0) b : f32; |
| 831 | // }; |
| 832 | // struct Input { |
| 833 | // a : Inner; |
| 834 | // }; |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 835 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 836 | // fn main(param : Input) {} |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 837 | auto* inner = |
| 838 | Structure("Inner", Vector{ |
| 839 | Member(Source{{13, 43}}, "a", ty.f32(), Vector{Location(0_a)}), |
| 840 | }); |
| 841 | auto* input = Structure("Input", Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 842 | Member(Source{{14, 52}}, "a", ty.Of(inner)), |
| 843 | }); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 844 | auto* param = Param("param", ty.Of(input)); |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 845 | Func(Source{{12, 34}}, "main", |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 846 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 847 | param, |
| 848 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 849 | ty.void_(), tint::Empty, |
| 850 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 851 | Stage(ast::PipelineStage::kFragment), |
| 852 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 853 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 854 | EXPECT_FALSE(r()->Resolve()); |
| 855 | EXPECT_EQ(r()->error(), |
Ben Clayton | 4d3ff97 | 2023-02-21 17:33:54 +0000 | [diff] [blame] | 856 | R"(14:52 error: nested structures cannot be used for entry point IO |
| 857 | 12:34 note: while analyzing entry point 'main')"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 858 | } |
| 859 | |
| 860 | TEST_F(LocationAttributeTests, BadType_Input_Struct_RuntimeArray) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 861 | // struct Input { |
| 862 | // @location(0) a : array<f32>; |
| 863 | // }; |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 864 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 865 | // fn main(param : Input) {} |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 866 | auto* input = Structure( |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 867 | "Input", Vector{ |
| 868 | Member(Source{{13, 43}}, "a", ty.array<f32>(), Vector{Location(0_a)}), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 869 | }); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 870 | auto* param = Param("param", ty.Of(input)); |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 871 | Func(Source{{12, 34}}, "main", |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 872 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 873 | param, |
| 874 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 875 | ty.void_(), tint::Empty, |
| 876 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 877 | Stage(ast::PipelineStage::kFragment), |
| 878 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 879 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 880 | EXPECT_FALSE(r()->Resolve()); |
| 881 | EXPECT_EQ(r()->error(), |
Ben Clayton | 710b62f | 2024-02-26 20:24:06 +0000 | [diff] [blame] | 882 | R"(13:43 error: cannot apply '@location' to declaration of type 'array<f32>' |
| 883 | note: '@location' must only be applied to declarations of numeric scalar or numeric vector type)"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 884 | } |
| 885 | |
| 886 | TEST_F(LocationAttributeTests, BadMemberType_Input) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 887 | // struct S { @location(0) m: array<i32>; }; |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 888 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 889 | // fn frag_main( a: S) {} |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 890 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 891 | auto* m = Member(Source{{34, 56}}, "m", ty.array<i32>(), |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 892 | Vector{ |
dan sinclair | f9eeed6 | 2022-09-07 22:25:24 +0000 | [diff] [blame] | 893 | Location(Source{{12, 34}}, 0_u), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 894 | }); |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 895 | auto* s = Structure("S", Vector{m}); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 896 | auto* p = Param("a", ty.Of(s)); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 897 | |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 898 | Func("frag_main", |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 899 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 900 | p, |
| 901 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 902 | ty.void_(), tint::Empty, |
| 903 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 904 | Stage(ast::PipelineStage::kFragment), |
| 905 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 906 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 907 | EXPECT_FALSE(r()->Resolve()); |
| 908 | EXPECT_EQ(r()->error(), |
Ben Clayton | 710b62f | 2024-02-26 20:24:06 +0000 | [diff] [blame] | 909 | R"(34:56 error: cannot apply '@location' to declaration of type 'array<i32>' |
| 910 | 12:34 note: '@location' must only be applied to declarations of numeric scalar or numeric vector type)"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 911 | } |
| 912 | |
| 913 | TEST_F(LocationAttributeTests, BadMemberType_Output) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 914 | // struct S { @location(0) m: atomic<i32>; }; |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 915 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 916 | // fn frag_main() -> S {} |
| 917 | auto* m = Member(Source{{34, 56}}, "m", ty.atomic<i32>(), |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 918 | Vector{ |
dan sinclair | f9eeed6 | 2022-09-07 22:25:24 +0000 | [diff] [blame] | 919 | Location(Source{{12, 34}}, 0_u), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 920 | }); |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 921 | auto* s = Structure("S", Vector{m}); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 922 | |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 923 | Func("frag_main", tint::Empty, ty.Of(s), |
| 924 | Vector{ |
Ben Clayton | 01ac21c | 2023-02-07 16:14:25 +0000 | [diff] [blame] | 925 | Return(Call(ty.Of(s))), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 926 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 927 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 928 | Stage(ast::PipelineStage::kFragment), |
| 929 | }, |
| 930 | {}); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 931 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 932 | EXPECT_FALSE(r()->Resolve()); |
| 933 | EXPECT_EQ(r()->error(), |
Ben Clayton | 710b62f | 2024-02-26 20:24:06 +0000 | [diff] [blame] | 934 | R"(34:56 error: cannot apply '@location' to declaration of type 'atomic<i32>' |
| 935 | 12:34 note: '@location' must only be applied to declarations of numeric scalar or numeric vector type)"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 936 | } |
| 937 | |
| 938 | TEST_F(LocationAttributeTests, BadMemberType_Unused) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 939 | // struct S { @location(0) m: mat3x2<f32>; }; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 940 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 941 | auto* m = Member(Source{{34, 56}}, "m", ty.mat3x2<f32>(), |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 942 | Vector{ |
dan sinclair | f9eeed6 | 2022-09-07 22:25:24 +0000 | [diff] [blame] | 943 | Location(Source{{12, 34}}, 0_u), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 944 | }); |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 945 | Structure("S", Vector{m}); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 946 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 947 | EXPECT_FALSE(r()->Resolve()); |
| 948 | EXPECT_EQ(r()->error(), |
Ben Clayton | 710b62f | 2024-02-26 20:24:06 +0000 | [diff] [blame] | 949 | R"(34:56 error: cannot apply '@location' to declaration of type 'mat3x2<f32>' |
| 950 | 12:34 note: '@location' must only be applied to declarations of numeric scalar or numeric vector type)"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 951 | } |
| 952 | |
| 953 | TEST_F(LocationAttributeTests, ReturnType_Struct_Valid) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 954 | // struct Output { |
| 955 | // @location(0) a : f32; |
| 956 | // @builtin(frag_depth) b : f32; |
| 957 | // }; |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 958 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 959 | // fn main() -> Output { |
| 960 | // return Output(); |
| 961 | // } |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 962 | auto* output = Structure( |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 963 | "Output", Vector{ |
| 964 | Member("a", ty.f32(), Vector{Location(0_a)}), |
Ben Clayton | cd52f38 | 2023-08-07 13:11:08 +0000 | [diff] [blame] | 965 | Member("b", ty.f32(), Vector{Builtin(core::BuiltinValue::kFragDepth)}), |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 966 | }); |
| 967 | Func(Source{{12, 34}}, "main", tint::Empty, ty.Of(output), |
| 968 | Vector{ |
Ben Clayton | 01ac21c | 2023-02-07 16:14:25 +0000 | [diff] [blame] | 969 | Return(Call(ty.Of(output))), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 970 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 971 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 972 | Stage(ast::PipelineStage::kFragment), |
| 973 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 974 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 975 | EXPECT_TRUE(r()->Resolve()) << r()->error(); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 976 | } |
| 977 | |
| 978 | TEST_F(LocationAttributeTests, ReturnType_Struct) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 979 | // struct Output { |
| 980 | // a : f32; |
| 981 | // }; |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 982 | // @vertex |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 983 | // fn main() -> @location(0) Output { |
| 984 | // return Output(); |
| 985 | // } |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 986 | auto* output = Structure("Output", Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 987 | Member("a", ty.f32()), |
| 988 | }); |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 989 | Func(Source{{12, 34}}, "main", tint::Empty, ty.Of(output), |
| 990 | Vector{ |
Ben Clayton | 01ac21c | 2023-02-07 16:14:25 +0000 | [diff] [blame] | 991 | Return(Call(ty.Of(output))), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 992 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 993 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 994 | Stage(ast::PipelineStage::kVertex), |
| 995 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 996 | Vector{ |
dan sinclair | f9eeed6 | 2022-09-07 22:25:24 +0000 | [diff] [blame] | 997 | Location(Source{{13, 43}}, 0_a), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 998 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 999 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 1000 | EXPECT_FALSE(r()->Resolve()); |
Ben Clayton | 710b62f | 2024-02-26 20:24:06 +0000 | [diff] [blame] | 1001 | EXPECT_EQ(r()->error(), R"(12:34 error: cannot apply '@location' to declaration of type 'Output' |
| 1002 | 13:43 note: '@location' must only be applied to declarations of numeric scalar or numeric vector type)"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 1003 | } |
| 1004 | |
| 1005 | TEST_F(LocationAttributeTests, ReturnType_Struct_NestedStruct) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 1006 | // struct Inner { |
| 1007 | // @location(0) b : f32; |
| 1008 | // }; |
| 1009 | // struct Output { |
| 1010 | // a : Inner; |
| 1011 | // }; |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 1012 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 1013 | // fn main() -> Output { return Output(); } |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 1014 | auto* inner = |
| 1015 | Structure("Inner", Vector{ |
| 1016 | Member(Source{{13, 43}}, "a", ty.f32(), Vector{Location(0_a)}), |
| 1017 | }); |
| 1018 | auto* output = Structure("Output", Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1019 | Member(Source{{14, 52}}, "a", ty.Of(inner)), |
| 1020 | }); |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 1021 | Func(Source{{12, 34}}, "main", tint::Empty, ty.Of(output), |
| 1022 | Vector{ |
Ben Clayton | 01ac21c | 2023-02-07 16:14:25 +0000 | [diff] [blame] | 1023 | Return(Call(ty.Of(output))), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1024 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 1025 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1026 | Stage(ast::PipelineStage::kFragment), |
| 1027 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 1028 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 1029 | EXPECT_FALSE(r()->Resolve()); |
| 1030 | EXPECT_EQ(r()->error(), |
Ben Clayton | 4d3ff97 | 2023-02-21 17:33:54 +0000 | [diff] [blame] | 1031 | R"(14:52 error: nested structures cannot be used for entry point IO |
| 1032 | 12:34 note: while analyzing entry point 'main')"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 1033 | } |
| 1034 | |
| 1035 | TEST_F(LocationAttributeTests, ReturnType_Struct_RuntimeArray) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 1036 | // struct Output { |
| 1037 | // @location(0) a : array<f32>; |
| 1038 | // }; |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 1039 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 1040 | // fn main() -> Output { |
| 1041 | // return Output(); |
| 1042 | // } |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 1043 | auto* output = Structure("Output", Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1044 | Member(Source{{13, 43}}, "a", ty.array<f32>(), |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 1045 | Vector{Location(Source{{12, 34}}, 0_a)}), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1046 | }); |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 1047 | Func(Source{{12, 34}}, "main", tint::Empty, ty.Of(output), |
| 1048 | Vector{ |
Ben Clayton | 01ac21c | 2023-02-07 16:14:25 +0000 | [diff] [blame] | 1049 | Return(Call(ty.Of(output))), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1050 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 1051 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1052 | Stage(ast::PipelineStage::kFragment), |
| 1053 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 1054 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 1055 | EXPECT_FALSE(r()->Resolve()); |
| 1056 | EXPECT_EQ(r()->error(), |
Ben Clayton | 710b62f | 2024-02-26 20:24:06 +0000 | [diff] [blame] | 1057 | R"(13:43 error: cannot apply '@location' to declaration of type 'array<f32>' |
| 1058 | 12:34 note: '@location' must only be applied to declarations of numeric scalar or numeric vector type)"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 1059 | } |
| 1060 | |
| 1061 | TEST_F(LocationAttributeTests, ComputeShaderLocation_Input) { |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 1062 | Func("main", tint::Empty, ty.i32(), |
| 1063 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1064 | Return(Expr(1_i)), |
| 1065 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 1066 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1067 | Stage(ast::PipelineStage::kCompute), |
| 1068 | create<ast::WorkgroupAttribute>(Source{{12, 34}}, Expr(1_i)), |
| 1069 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 1070 | Vector{ |
dan sinclair | f9eeed6 | 2022-09-07 22:25:24 +0000 | [diff] [blame] | 1071 | Location(Source{{12, 34}}, 1_a), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1072 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 1073 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 1074 | EXPECT_FALSE(r()->Resolve()); |
Ben Clayton | 710b62f | 2024-02-26 20:24:06 +0000 | [diff] [blame] | 1075 | EXPECT_EQ(r()->error(), R"(12:34 error: '@location' cannot be used by compute shaders)"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 1076 | } |
| 1077 | |
| 1078 | TEST_F(LocationAttributeTests, ComputeShaderLocation_Output) { |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1079 | auto* input = Param("input", ty.i32(), |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 1080 | Vector{ |
dan sinclair | f9eeed6 | 2022-09-07 22:25:24 +0000 | [diff] [blame] | 1081 | Location(Source{{12, 34}}, 0_u), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1082 | }); |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 1083 | Func("main", Vector{input}, ty.void_(), tint::Empty, |
| 1084 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1085 | Stage(ast::PipelineStage::kCompute), |
| 1086 | create<ast::WorkgroupAttribute>(Source{{12, 34}}, Expr(1_i)), |
| 1087 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 1088 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 1089 | EXPECT_FALSE(r()->Resolve()); |
Ben Clayton | 710b62f | 2024-02-26 20:24:06 +0000 | [diff] [blame] | 1090 | EXPECT_EQ(r()->error(), R"(12:34 error: '@location' cannot be used by compute shaders)"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 1091 | } |
| 1092 | |
| 1093 | TEST_F(LocationAttributeTests, ComputeShaderLocationStructMember_Output) { |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1094 | auto* m = Member("m", ty.i32(), |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 1095 | Vector{ |
dan sinclair | f9eeed6 | 2022-09-07 22:25:24 +0000 | [diff] [blame] | 1096 | Location(Source{{12, 34}}, 0_u), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1097 | }); |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 1098 | auto* s = Structure("S", Vector{m}); |
| 1099 | Func(Source{{56, 78}}, "main", tint::Empty, ty.Of(s), |
| 1100 | Vector{ |
Ben Clayton | 01ac21c | 2023-02-07 16:14:25 +0000 | [diff] [blame] | 1101 | Return(Expr(Call(ty.Of(s)))), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1102 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 1103 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1104 | Stage(ast::PipelineStage::kCompute), |
| 1105 | create<ast::WorkgroupAttribute>(Source{{12, 34}}, Expr(1_i)), |
| 1106 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 1107 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 1108 | EXPECT_FALSE(r()->Resolve()); |
Ben Clayton | 710b62f | 2024-02-26 20:24:06 +0000 | [diff] [blame] | 1109 | EXPECT_EQ(r()->error(), R"(12:34 error: '@location' cannot be used by compute shaders |
| 1110 | 56:78 note: while analyzing entry point 'main')"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 1111 | } |
| 1112 | |
| 1113 | TEST_F(LocationAttributeTests, ComputeShaderLocationStructMember_Input) { |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1114 | auto* m = Member("m", ty.i32(), |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 1115 | Vector{ |
dan sinclair | f9eeed6 | 2022-09-07 22:25:24 +0000 | [diff] [blame] | 1116 | Location(Source{{12, 34}}, 0_u), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1117 | }); |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 1118 | auto* s = Structure("S", Vector{m}); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 1119 | auto* input = Param("input", ty.Of(s)); |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 1120 | Func(Source{{56, 78}}, "main", Vector{input}, ty.void_(), tint::Empty, |
| 1121 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1122 | Stage(ast::PipelineStage::kCompute), |
| 1123 | create<ast::WorkgroupAttribute>(Source{{12, 34}}, Expr(1_i)), |
| 1124 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 1125 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 1126 | EXPECT_FALSE(r()->Resolve()); |
Ben Clayton | 710b62f | 2024-02-26 20:24:06 +0000 | [diff] [blame] | 1127 | EXPECT_EQ(r()->error(), R"(12:34 error: '@location' cannot be used by compute shaders |
| 1128 | 56:78 note: while analyzing entry point 'main')"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 1129 | } |
| 1130 | |
| 1131 | TEST_F(LocationAttributeTests, Duplicate_input) { |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 1132 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 1133 | // fn main(@location(1) param_a : f32, |
| 1134 | // @location(1) param_b : f32) {} |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1135 | auto* param_a = Param("param_a", ty.f32(), |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 1136 | Vector{ |
dan sinclair | f9eeed6 | 2022-09-07 22:25:24 +0000 | [diff] [blame] | 1137 | Location(1_a), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1138 | }); |
| 1139 | auto* param_b = Param("param_b", ty.f32(), |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 1140 | Vector{ |
dan sinclair | f9eeed6 | 2022-09-07 22:25:24 +0000 | [diff] [blame] | 1141 | Location(Source{{12, 34}}, 1_a), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1142 | }); |
| 1143 | Func(Source{{12, 34}}, "main", |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 1144 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1145 | param_a, |
| 1146 | param_b, |
| 1147 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 1148 | ty.void_(), tint::Empty, |
| 1149 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1150 | Stage(ast::PipelineStage::kFragment), |
| 1151 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 1152 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 1153 | EXPECT_FALSE(r()->Resolve()); |
Ben Clayton | 710b62f | 2024-02-26 20:24:06 +0000 | [diff] [blame] | 1154 | EXPECT_EQ(r()->error(), R"(12:34 error: '@location(1)' appears multiple times)"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 1155 | } |
| 1156 | |
| 1157 | TEST_F(LocationAttributeTests, Duplicate_struct) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 1158 | // struct InputA { |
| 1159 | // @location(1) a : f32; |
| 1160 | // }; |
| 1161 | // struct InputB { |
| 1162 | // @location(1) a : f32; |
| 1163 | // }; |
dan sinclair | b29892b | 2022-06-07 13:55:34 +0000 | [diff] [blame] | 1164 | // @fragment |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 1165 | // fn main(param_a : InputA, param_b : InputB) {} |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 1166 | auto* input_a = Structure("InputA", Vector{ |
| 1167 | Member("a", ty.f32(), Vector{Location(1_a)}), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1168 | }); |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 1169 | auto* input_b = |
| 1170 | Structure("InputB", Vector{ |
| 1171 | Member("a", ty.f32(), Vector{Location(Source{{34, 56}}, 1_a)}), |
| 1172 | }); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 1173 | auto* param_a = Param("param_a", ty.Of(input_a)); |
| 1174 | auto* param_b = Param("param_b", ty.Of(input_b)); |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1175 | Func(Source{{12, 34}}, "main", |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 1176 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1177 | param_a, |
| 1178 | param_b, |
| 1179 | }, |
dan sinclair | bae54e7 | 2023-07-28 15:01:54 +0000 | [diff] [blame] | 1180 | ty.void_(), tint::Empty, |
| 1181 | Vector{ |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 1182 | Stage(ast::PipelineStage::kFragment), |
| 1183 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 1184 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 1185 | EXPECT_FALSE(r()->Resolve()); |
| 1186 | EXPECT_EQ(r()->error(), |
Ben Clayton | 710b62f | 2024-02-26 20:24:06 +0000 | [diff] [blame] | 1187 | R"(34:56 error: '@location(1)' appears multiple times |
Ben Clayton | 4d3ff97 | 2023-02-21 17:33:54 +0000 | [diff] [blame] | 1188 | 12:34 note: while analyzing entry point 'main')"); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 1189 | } |
| 1190 | |
| 1191 | } // namespace |
| 1192 | } // namespace LocationAttributeTests |
| 1193 | |
| 1194 | } // namespace |
dan sinclair | d209379 | 2022-04-07 17:45:45 +0000 | [diff] [blame] | 1195 | } // namespace tint::resolver |