Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 1 | // Copyright 2020 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 "gmock/gmock.h" |
| 16 | #include "src/tint/reader/spirv/function.h" |
| 17 | #include "src/tint/reader/spirv/parser_impl_test_helper.h" |
| 18 | #include "src/tint/reader/spirv/spirv_tools_helpers_test.h" |
| 19 | |
dan sinclair | 258cbaf | 2022-04-07 19:01:25 +0000 | [diff] [blame] | 20 | namespace tint::reader::spirv { |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 21 | namespace { |
| 22 | |
| 23 | using ::testing::HasSubstr; |
| 24 | |
| 25 | std::string Preamble() { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 26 | return R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 27 | OpCapability Shader |
| 28 | OpMemoryModel Logical Simple |
| 29 | OpEntryPoint Fragment %100 "main" |
| 30 | OpExecutionMode %100 OriginUpperLeft |
| 31 | |
| 32 | %void = OpTypeVoid |
| 33 | %voidfn = OpTypeFunction %void |
| 34 | |
| 35 | %uint = OpTypeInt 32 0 |
| 36 | %int = OpTypeInt 32 1 |
| 37 | %float = OpTypeFloat 32 |
| 38 | |
| 39 | %uint_10 = OpConstant %uint 10 |
| 40 | %uint_20 = OpConstant %uint 20 |
| 41 | %int_30 = OpConstant %int 30 |
| 42 | %int_40 = OpConstant %int 40 |
| 43 | %float_50 = OpConstant %float 50 |
| 44 | %float_60 = OpConstant %float 60 |
| 45 | %float_70 = OpConstant %float 70 |
| 46 | |
| 47 | %ptr_uint = OpTypePointer Function %uint |
| 48 | %ptr_int = OpTypePointer Function %int |
| 49 | %ptr_float = OpTypePointer Function %float |
| 50 | |
| 51 | %v2uint = OpTypeVector %uint 2 |
| 52 | %v2int = OpTypeVector %int 2 |
| 53 | %v2float = OpTypeVector %float 2 |
| 54 | %v3float = OpTypeVector %float 3 |
| 55 | |
| 56 | %v2uint_10_20 = OpConstantComposite %v2uint %uint_10 %uint_20 |
| 57 | %v2uint_20_10 = OpConstantComposite %v2uint %uint_20 %uint_10 |
| 58 | %v2int_30_40 = OpConstantComposite %v2int %int_30 %int_40 |
| 59 | %v2int_40_30 = OpConstantComposite %v2int %int_40 %int_30 |
| 60 | %v2float_50_60 = OpConstantComposite %v2float %float_50 %float_60 |
| 61 | %v2float_60_50 = OpConstantComposite %v2float %float_60 %float_50 |
| 62 | %v3float_50_60_70 = OpConstantComposite %v3float %float_50 %float_60 %float_70 |
| 63 | %v3float_60_70_50 = OpConstantComposite %v3float %float_60 %float_70 %float_50 |
| 64 | |
| 65 | %m2v2float = OpTypeMatrix %v2float 2 |
| 66 | %m2v3float = OpTypeMatrix %v3float 2 |
| 67 | %m3v2float = OpTypeMatrix %v2float 3 |
| 68 | %m2v2float_a = OpConstantComposite %m2v2float %v2float_50_60 %v2float_60_50 |
| 69 | %m2v2float_b = OpConstantComposite %m2v2float %v2float_60_50 %v2float_50_60 |
| 70 | %m3v2float_a = OpConstantComposite %m3v2float %v2float_50_60 %v2float_60_50 %v2float_50_60 |
| 71 | %m2v3float_a = OpConstantComposite %m2v3float %v3float_50_60_70 %v3float_60_70_50 |
| 72 | )"; |
| 73 | } |
| 74 | |
| 75 | // Returns the AST dump for a given SPIR-V assembly constant. |
| 76 | std::string AstFor(std::string assembly) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 77 | if (assembly == "v2uint_10_20") { |
| 78 | return "vec2<u32>(10u, 20u)"; |
| 79 | } |
| 80 | if (assembly == "v2uint_20_10") { |
| 81 | return "vec2<u32>(20u, 10u)"; |
| 82 | } |
| 83 | if (assembly == "v2int_30_40") { |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 84 | return "vec2<i32>(30i, 40i)"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 85 | } |
| 86 | if (assembly == "v2int_40_30") { |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 87 | return "vec2<i32>(40i, 30i)"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 88 | } |
| 89 | if (assembly == "cast_int_v2uint_10_20") { |
| 90 | return "bitcast<vec2<i32>>(vec2<u32>(10u, 20u))"; |
| 91 | } |
| 92 | if (assembly == "cast_uint_v2int_40_30") { |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 93 | return "bitcast<vec2<u32>>(vec2<i32>(40i, 30i))"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 94 | } |
| 95 | if (assembly == "v2float_50_60") { |
| 96 | return "vec2<f32>(50.0, 60.0)"; |
| 97 | } |
| 98 | if (assembly == "v2float_60_50") { |
| 99 | return "vec2<f32>(60.0, 50.0)"; |
| 100 | } |
| 101 | return "bad case"; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 102 | } |
| 103 | |
| 104 | using SpvUnaryArithTest = SpvParserTestBase<::testing::Test>; |
| 105 | |
| 106 | TEST_F(SpvUnaryArithTest, SNegate_Int_Int) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 107 | const auto assembly = Preamble() + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 108 | %100 = OpFunction %void None %voidfn |
| 109 | %entry = OpLabel |
| 110 | %1 = OpSNegate %int %int_30 |
| 111 | OpReturn |
| 112 | OpFunctionEnd |
| 113 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 114 | auto p = parser(test::Assemble(assembly)); |
| 115 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error() << "\n" << assembly; |
| 116 | auto fe = p->function_emitter(100); |
| 117 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 118 | auto ast_body = fe.ast_body(); |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 119 | EXPECT_THAT(test::ToString(p->program(), ast_body), HasSubstr("let x_1 : i32 = -(30i);")); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 120 | } |
| 121 | |
| 122 | TEST_F(SpvUnaryArithTest, SNegate_Int_Uint) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 123 | const auto assembly = Preamble() + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 124 | %100 = OpFunction %void None %voidfn |
| 125 | %entry = OpLabel |
| 126 | %1 = OpSNegate %int %uint_10 |
| 127 | OpReturn |
| 128 | OpFunctionEnd |
| 129 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 130 | auto p = parser(test::Assemble(assembly)); |
| 131 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error() << "\n" << assembly; |
| 132 | auto fe = p->function_emitter(100); |
| 133 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 134 | auto ast_body = fe.ast_body(); |
| 135 | EXPECT_THAT(test::ToString(p->program(), ast_body), |
| 136 | HasSubstr("let x_1 : i32 = -(bitcast<i32>(10u));")); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 137 | } |
| 138 | |
| 139 | TEST_F(SpvUnaryArithTest, SNegate_Uint_Int) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 140 | const auto assembly = Preamble() + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 141 | %100 = OpFunction %void None %voidfn |
| 142 | %entry = OpLabel |
| 143 | %1 = OpSNegate %uint %int_30 |
| 144 | OpReturn |
| 145 | OpFunctionEnd |
| 146 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 147 | auto p = parser(test::Assemble(assembly)); |
| 148 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error() << "\n" << assembly; |
| 149 | auto fe = p->function_emitter(100); |
| 150 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 151 | auto ast_body = fe.ast_body(); |
| 152 | EXPECT_THAT(test::ToString(p->program(), ast_body), |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 153 | HasSubstr("let x_1 : u32 = bitcast<u32>(-(30i));")); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 154 | } |
| 155 | |
| 156 | TEST_F(SpvUnaryArithTest, SNegate_Uint_Uint) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 157 | const auto assembly = Preamble() + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 158 | %100 = OpFunction %void None %voidfn |
| 159 | %entry = OpLabel |
| 160 | %1 = OpSNegate %uint %uint_10 |
| 161 | OpReturn |
| 162 | OpFunctionEnd |
| 163 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 164 | auto p = parser(test::Assemble(assembly)); |
| 165 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error() << "\n" << assembly; |
| 166 | auto fe = p->function_emitter(100); |
| 167 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 168 | auto ast_body = fe.ast_body(); |
| 169 | EXPECT_THAT(test::ToString(p->program(), ast_body), |
| 170 | HasSubstr("let x_1 : u32 = bitcast<u32>(-(bitcast<i32>(10u)));")); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 171 | } |
| 172 | |
| 173 | TEST_F(SpvUnaryArithTest, SNegate_SignedVec_SignedVec) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 174 | const auto assembly = Preamble() + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 175 | %100 = OpFunction %void None %voidfn |
| 176 | %entry = OpLabel |
| 177 | %1 = OpSNegate %v2int %v2int_30_40 |
| 178 | OpReturn |
| 179 | OpFunctionEnd |
| 180 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 181 | auto p = parser(test::Assemble(assembly)); |
| 182 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error() << "\n" << assembly; |
| 183 | auto fe = p->function_emitter(100); |
| 184 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 185 | auto ast_body = fe.ast_body(); |
| 186 | EXPECT_THAT(test::ToString(p->program(), ast_body), |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 187 | HasSubstr("let x_1 : vec2<i32> = -(vec2<i32>(30i, 40i));")); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 188 | } |
| 189 | |
| 190 | TEST_F(SpvUnaryArithTest, SNegate_SignedVec_UnsignedVec) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 191 | const auto assembly = Preamble() + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 192 | %100 = OpFunction %void None %voidfn |
| 193 | %entry = OpLabel |
| 194 | %1 = OpSNegate %v2int %v2uint_10_20 |
| 195 | OpReturn |
| 196 | OpFunctionEnd |
| 197 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 198 | auto p = parser(test::Assemble(assembly)); |
| 199 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error() << "\n" << assembly; |
| 200 | auto fe = p->function_emitter(100); |
| 201 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 202 | auto ast_body = fe.ast_body(); |
| 203 | EXPECT_THAT(test::ToString(p->program(), ast_body), |
| 204 | HasSubstr("let x_1 : vec2<i32> = -(bitcast<vec2<i32>>(vec2<u32>(10u, 20u)));")); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 205 | } |
| 206 | |
| 207 | TEST_F(SpvUnaryArithTest, SNegate_UnsignedVec_SignedVec) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 208 | const auto assembly = Preamble() + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 209 | %100 = OpFunction %void None %voidfn |
| 210 | %entry = OpLabel |
| 211 | %1 = OpSNegate %v2uint %v2int_30_40 |
| 212 | OpReturn |
| 213 | OpFunctionEnd |
| 214 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 215 | auto p = parser(test::Assemble(assembly)); |
| 216 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error() << "\n" << assembly; |
| 217 | auto fe = p->function_emitter(100); |
| 218 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 219 | auto ast_body = fe.ast_body(); |
| 220 | EXPECT_THAT(test::ToString(p->program(), ast_body), |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 221 | HasSubstr("let x_1 : vec2<u32> = bitcast<vec2<u32>>(-(vec2<i32>(30i, 40i)));")); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 222 | } |
| 223 | |
| 224 | TEST_F(SpvUnaryArithTest, SNegate_UnsignedVec_UnsignedVec) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 225 | const auto assembly = Preamble() + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 226 | %100 = OpFunction %void None %voidfn |
| 227 | %entry = OpLabel |
| 228 | %1 = OpSNegate %v2uint %v2uint_10_20 |
| 229 | OpReturn |
| 230 | OpFunctionEnd |
| 231 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 232 | auto p = parser(test::Assemble(assembly)); |
| 233 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error() << "\n" << assembly; |
| 234 | auto fe = p->function_emitter(100); |
| 235 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 236 | auto ast_body = fe.ast_body(); |
| 237 | EXPECT_THAT( |
| 238 | test::ToString(p->program(), ast_body), |
| 239 | HasSubstr( |
| 240 | R"(let x_1 : vec2<u32> = bitcast<vec2<u32>>(-(bitcast<vec2<i32>>(vec2<u32>(10u, 20u))));)")); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 241 | } |
| 242 | |
| 243 | TEST_F(SpvUnaryArithTest, FNegate_Scalar) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 244 | const auto assembly = Preamble() + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 245 | %100 = OpFunction %void None %voidfn |
| 246 | %entry = OpLabel |
| 247 | %1 = OpFNegate %float %float_50 |
| 248 | OpReturn |
| 249 | OpFunctionEnd |
| 250 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 251 | auto p = parser(test::Assemble(assembly)); |
| 252 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error() << "\n" << assembly; |
| 253 | auto fe = p->function_emitter(100); |
| 254 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 255 | auto ast_body = fe.ast_body(); |
| 256 | EXPECT_THAT(test::ToString(p->program(), ast_body), HasSubstr("let x_1 : f32 = -(50.0);")); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 257 | } |
| 258 | |
| 259 | TEST_F(SpvUnaryArithTest, FNegate_Vector) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 260 | const auto assembly = Preamble() + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 261 | %100 = OpFunction %void None %voidfn |
| 262 | %entry = OpLabel |
| 263 | %1 = OpFNegate %v2float %v2float_50_60 |
| 264 | OpReturn |
| 265 | OpFunctionEnd |
| 266 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 267 | auto p = parser(test::Assemble(assembly)); |
| 268 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error() << "\n" << assembly; |
| 269 | auto fe = p->function_emitter(100); |
| 270 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 271 | auto ast_body = fe.ast_body(); |
| 272 | EXPECT_THAT(test::ToString(p->program(), ast_body), |
| 273 | HasSubstr("let x_1 : vec2<f32> = -(vec2<f32>(50.0, 60.0));")); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 274 | } |
| 275 | |
| 276 | struct BinaryData { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 277 | const std::string res_type; |
| 278 | const std::string lhs; |
| 279 | const std::string op; |
| 280 | const std::string rhs; |
| 281 | const std::string ast_type; |
| 282 | const std::string ast_lhs; |
| 283 | const std::string ast_op; |
| 284 | const std::string ast_rhs; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 285 | }; |
| 286 | inline std::ostream& operator<<(std::ostream& out, BinaryData data) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 287 | out << "BinaryData{" << data.res_type << "," << data.lhs << "," << data.op << "," << data.rhs |
| 288 | << "," << data.ast_type << "," << data.ast_lhs << "," << data.ast_op << "," << data.ast_rhs |
| 289 | << "}"; |
| 290 | return out; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 291 | } |
| 292 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 293 | using SpvBinaryArithTest = SpvParserTestBase<::testing::TestWithParam<BinaryData>>; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 294 | using SpvBinaryArithTestBasic = SpvParserTestBase<::testing::Test>; |
| 295 | |
| 296 | TEST_P(SpvBinaryArithTest, EmitExpression) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 297 | const auto assembly = Preamble() + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 298 | %100 = OpFunction %void None %voidfn |
| 299 | %entry = OpLabel |
| 300 | %1 = )" + GetParam().op + |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 301 | " %" + GetParam().res_type + " %" + GetParam().lhs + " %" + |
| 302 | GetParam().rhs + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 303 | OpReturn |
| 304 | OpFunctionEnd |
| 305 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 306 | auto p = parser(test::Assemble(assembly)); |
| 307 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error() << "\n" << assembly; |
| 308 | auto fe = p->function_emitter(100); |
| 309 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 310 | std::ostringstream ss; |
| 311 | ss << "let x_1 : " << GetParam().ast_type << " = (" << GetParam().ast_lhs << " " |
| 312 | << GetParam().ast_op << " " << GetParam().ast_rhs << ");"; |
| 313 | auto ast_body = fe.ast_body(); |
| 314 | auto got = test::ToString(p->program(), ast_body); |
| 315 | EXPECT_THAT(got, HasSubstr(ss.str())) << "got:\n" << got << assembly; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 316 | } |
| 317 | |
| 318 | // Use this when the result might have extra bitcasts on the outside. |
| 319 | struct BinaryDataGeneral { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 320 | const std::string res_type; |
| 321 | const std::string lhs; |
| 322 | const std::string op; |
| 323 | const std::string rhs; |
| 324 | const std::string wgsl_type; |
| 325 | const std::string expected; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 326 | }; |
| 327 | inline std::ostream& operator<<(std::ostream& out, BinaryDataGeneral data) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 328 | out << "BinaryDataGeneral{" << data.res_type << "," << data.lhs << "," << data.op << "," |
| 329 | << data.rhs << "," << data.wgsl_type << "," << data.expected << "}"; |
| 330 | return out; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 331 | } |
| 332 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 333 | using SpvBinaryArithGeneralTest = SpvParserTestBase<::testing::TestWithParam<BinaryDataGeneral>>; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 334 | |
| 335 | TEST_P(SpvBinaryArithGeneralTest, EmitExpression) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 336 | const auto assembly = Preamble() + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 337 | %100 = OpFunction %void None %voidfn |
| 338 | %entry = OpLabel |
| 339 | %1 = )" + GetParam().op + |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 340 | " %" + GetParam().res_type + " %" + GetParam().lhs + " %" + |
| 341 | GetParam().rhs + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 342 | OpReturn |
| 343 | OpFunctionEnd |
| 344 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 345 | auto p = parser(test::Assemble(assembly)); |
| 346 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error() << "\n" << assembly; |
| 347 | auto fe = p->function_emitter(100); |
| 348 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 349 | std::ostringstream ss; |
| 350 | ss << "let x_1 : " << GetParam().wgsl_type << " = " << GetParam().expected << ";"; |
| 351 | auto ast_body = fe.ast_body(); |
| 352 | auto got = test::ToString(p->program(), ast_body); |
| 353 | EXPECT_THAT(got, HasSubstr(ss.str())) << "got:\n" << got << assembly; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 354 | } |
| 355 | |
| 356 | INSTANTIATE_TEST_SUITE_P( |
| 357 | SpvParserTest_IAdd, |
| 358 | SpvBinaryArithTest, |
| 359 | ::testing::Values( |
| 360 | // Both uint |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 361 | BinaryData{"uint", "uint_10", "OpIAdd", "uint_20", "u32", "10u", "+", "20u"}, // Both int |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 362 | BinaryData{"int", "int_30", "OpIAdd", "int_40", "i32", "30i", "+", "40i"}, // Both v2uint |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 363 | BinaryData{"v2uint", "v2uint_10_20", "OpIAdd", "v2uint_20_10", "vec2<u32>", |
| 364 | AstFor("v2uint_10_20"), "+", AstFor("v2uint_20_10")}, |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 365 | // Both v2int |
| 366 | BinaryData{"v2int", "v2int_30_40", "OpIAdd", "v2int_40_30", "vec2<i32>", |
| 367 | AstFor("v2int_30_40"), "+", AstFor("v2int_40_30")})); |
| 368 | |
| 369 | INSTANTIATE_TEST_SUITE_P( |
| 370 | SpvParserTest_IAdd_MixedSignedness, |
| 371 | SpvBinaryArithGeneralTest, |
| 372 | ::testing::Values( |
| 373 | // Mixed, uint <- int uint |
| 374 | BinaryDataGeneral{"uint", "int_30", "OpIAdd", "uint_10", "u32", |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 375 | "bitcast<u32>((30i + bitcast<i32>(10u)))"}, |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 376 | // Mixed, int <- int uint |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 377 | BinaryDataGeneral{"int", "int_30", "OpIAdd", "uint_10", "i32", "(30i + bitcast<i32>(10u))"}, |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 378 | // Mixed, uint <- uint int |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 379 | BinaryDataGeneral{"uint", "uint_10", "OpIAdd", "int_30", "u32", |
| 380 | "(10u + bitcast<u32>(30i))"}, |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 381 | // Mixed, int <- uint uint |
| 382 | BinaryDataGeneral{"int", "uint_20", "OpIAdd", "uint_10", "i32", |
| 383 | "bitcast<i32>((20u + 10u))"}, |
| 384 | // Mixed, returning v2uint |
| 385 | BinaryDataGeneral{ |
| 386 | "v2uint", "v2int_30_40", "OpIAdd", "v2uint_10_20", "vec2<u32>", |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 387 | R"(bitcast<vec2<u32>>((vec2<i32>(30i, 40i) + bitcast<vec2<i32>>(vec2<u32>(10u, 20u)))))"}, |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 388 | // Mixed, returning v2int |
| 389 | BinaryDataGeneral{ |
| 390 | "v2int", "v2uint_10_20", "OpIAdd", "v2int_40_30", "vec2<i32>", |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 391 | R"(bitcast<vec2<i32>>((vec2<u32>(10u, 20u) + bitcast<vec2<u32>>(vec2<i32>(40i, 30i)))))"})); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 392 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 393 | INSTANTIATE_TEST_SUITE_P(SpvParserTest_FAdd, |
| 394 | SpvBinaryArithTest, |
| 395 | ::testing::Values( |
| 396 | // Scalar float |
| 397 | BinaryData{"float", "float_50", "OpFAdd", "float_60", "f32", "50.0", |
| 398 | "+", "60.0"}, // Vector float |
| 399 | BinaryData{"v2float", "v2float_50_60", "OpFAdd", "v2float_60_50", |
| 400 | "vec2<f32>", AstFor("v2float_50_60"), "+", |
| 401 | AstFor("v2float_60_50")})); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 402 | |
| 403 | INSTANTIATE_TEST_SUITE_P( |
| 404 | SpvParserTest_ISub, |
| 405 | SpvBinaryArithTest, |
| 406 | ::testing::Values( |
| 407 | // Both uint |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 408 | BinaryData{"uint", "uint_10", "OpISub", "uint_20", "u32", "10u", "-", "20u"}, // Both int |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 409 | BinaryData{"int", "int_30", "OpISub", "int_40", "i32", "30i", "-", "40i"}, // Both v2uint |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 410 | BinaryData{"v2uint", "v2uint_10_20", "OpISub", "v2uint_20_10", "vec2<u32>", |
| 411 | AstFor("v2uint_10_20"), "-", AstFor("v2uint_20_10")}, |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 412 | // Both v2int |
| 413 | BinaryData{"v2int", "v2int_30_40", "OpISub", "v2int_40_30", "vec2<i32>", |
| 414 | AstFor("v2int_30_40"), "-", AstFor("v2int_40_30")})); |
| 415 | |
| 416 | INSTANTIATE_TEST_SUITE_P( |
| 417 | SpvParserTest_ISub_MixedSignedness, |
| 418 | SpvBinaryArithGeneralTest, |
| 419 | ::testing::Values( |
| 420 | // Mixed, uint <- int uint |
| 421 | BinaryDataGeneral{"uint", "int_30", "OpISub", "uint_10", "u32", |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 422 | R"(bitcast<u32>((30i - bitcast<i32>(10u))))"}, |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 423 | // Mixed, int <- int uint |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 424 | BinaryDataGeneral{"int", "int_30", "OpISub", "uint_10", "i32", "(30i - bitcast<i32>(10u))"}, |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 425 | // Mixed, uint <- uint int |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 426 | BinaryDataGeneral{"uint", "uint_10", "OpISub", "int_30", "u32", |
| 427 | "(10u - bitcast<u32>(30i))"}, |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 428 | // Mixed, int <- uint uint |
| 429 | BinaryDataGeneral{"int", "uint_20", "OpISub", "uint_10", "i32", |
| 430 | "bitcast<i32>((20u - 10u))"}, |
| 431 | // Mixed, returning v2uint |
| 432 | BinaryDataGeneral{ |
| 433 | "v2uint", "v2int_30_40", "OpISub", "v2uint_10_20", "vec2<u32>", |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 434 | R"(bitcast<vec2<u32>>((vec2<i32>(30i, 40i) - bitcast<vec2<i32>>(vec2<u32>(10u, 20u)))))"}, |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 435 | // Mixed, returning v2int |
| 436 | BinaryDataGeneral{ |
| 437 | "v2int", "v2uint_10_20", "OpISub", "v2int_40_30", "vec2<i32>", |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 438 | R"(bitcast<vec2<i32>>((vec2<u32>(10u, 20u) - bitcast<vec2<u32>>(vec2<i32>(40i, 30i)))))"})); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 439 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 440 | INSTANTIATE_TEST_SUITE_P(SpvParserTest_FSub, |
| 441 | SpvBinaryArithTest, |
| 442 | ::testing::Values( |
| 443 | // Scalar float |
| 444 | BinaryData{"float", "float_50", "OpFSub", "float_60", "f32", "50.0", |
| 445 | "-", "60.0"}, // Vector float |
| 446 | BinaryData{"v2float", "v2float_50_60", "OpFSub", "v2float_60_50", |
| 447 | "vec2<f32>", AstFor("v2float_50_60"), "-", |
| 448 | AstFor("v2float_60_50")})); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 449 | |
| 450 | INSTANTIATE_TEST_SUITE_P( |
| 451 | SpvParserTest_IMul, |
| 452 | SpvBinaryArithTest, |
| 453 | ::testing::Values( |
| 454 | // Both uint |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 455 | BinaryData{"uint", "uint_10", "OpIMul", "uint_20", "u32", "10u", "*", "20u"}, // Both int |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 456 | BinaryData{"int", "int_30", "OpIMul", "int_40", "i32", "30i", "*", "40i"}, // Both v2uint |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 457 | BinaryData{"v2uint", "v2uint_10_20", "OpIMul", "v2uint_20_10", "vec2<u32>", |
| 458 | AstFor("v2uint_10_20"), "*", AstFor("v2uint_20_10")}, |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 459 | // Both v2int |
| 460 | BinaryData{"v2int", "v2int_30_40", "OpIMul", "v2int_40_30", "vec2<i32>", |
| 461 | AstFor("v2int_30_40"), "*", AstFor("v2int_40_30")})); |
| 462 | |
| 463 | INSTANTIATE_TEST_SUITE_P( |
| 464 | SpvParserTest_IMul_MixedSignedness, |
| 465 | SpvBinaryArithGeneralTest, |
| 466 | ::testing::Values( |
| 467 | // Mixed, uint <- int uint |
| 468 | BinaryDataGeneral{"uint", "int_30", "OpIMul", "uint_10", "u32", |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 469 | "bitcast<u32>((30i * bitcast<i32>(10u)))"}, |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 470 | // Mixed, int <- int uint |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 471 | BinaryDataGeneral{"int", "int_30", "OpIMul", "uint_10", "i32", "(30i * bitcast<i32>(10u))"}, |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 472 | // Mixed, uint <- uint int |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 473 | BinaryDataGeneral{"uint", "uint_10", "OpIMul", "int_30", "u32", |
| 474 | "(10u * bitcast<u32>(30i))"}, |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 475 | // Mixed, int <- uint uint |
| 476 | BinaryDataGeneral{"int", "uint_20", "OpIMul", "uint_10", "i32", |
| 477 | "bitcast<i32>((20u * 10u))"}, |
| 478 | // Mixed, returning v2uint |
| 479 | BinaryDataGeneral{ |
| 480 | "v2uint", "v2int_30_40", "OpIMul", "v2uint_10_20", "vec2<u32>", |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 481 | R"(bitcast<vec2<u32>>((vec2<i32>(30i, 40i) * bitcast<vec2<i32>>(vec2<u32>(10u, 20u)))))"}, |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 482 | // Mixed, returning v2int |
| 483 | BinaryDataGeneral{ |
| 484 | "v2int", "v2uint_10_20", "OpIMul", "v2int_40_30", "vec2<i32>", |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 485 | R"(bitcast<vec2<i32>>((vec2<u32>(10u, 20u) * bitcast<vec2<u32>>(vec2<i32>(40i, 30i)))))"})); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 486 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 487 | INSTANTIATE_TEST_SUITE_P(SpvParserTest_FMul, |
| 488 | SpvBinaryArithTest, |
| 489 | ::testing::Values( |
| 490 | // Scalar float |
| 491 | BinaryData{"float", "float_50", "OpFMul", "float_60", "f32", "50.0", |
| 492 | "*", "60.0"}, // Vector float |
| 493 | BinaryData{"v2float", "v2float_50_60", "OpFMul", "v2float_60_50", |
| 494 | "vec2<f32>", AstFor("v2float_50_60"), "*", |
| 495 | AstFor("v2float_60_50")})); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 496 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 497 | INSTANTIATE_TEST_SUITE_P(SpvParserTest_UDiv, |
| 498 | SpvBinaryArithTest, |
| 499 | ::testing::Values( |
| 500 | // Both uint |
| 501 | BinaryData{"uint", "uint_10", "OpUDiv", "uint_20", "u32", "10u", "/", |
| 502 | "20u"}, // Both v2uint |
| 503 | BinaryData{"v2uint", "v2uint_10_20", "OpUDiv", "v2uint_20_10", |
| 504 | "vec2<u32>", AstFor("v2uint_10_20"), "/", |
| 505 | AstFor("v2uint_20_10")})); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 506 | |
| 507 | INSTANTIATE_TEST_SUITE_P( |
| 508 | SpvParserTest_SDiv, |
| 509 | SpvBinaryArithTest, |
| 510 | ::testing::Values( |
| 511 | // Both int |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 512 | BinaryData{"int", "int_30", "OpSDiv", "int_40", "i32", "30i", "/", "40i"}, // Both v2int |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 513 | BinaryData{"v2int", "v2int_30_40", "OpSDiv", "v2int_40_30", "vec2<i32>", |
| 514 | AstFor("v2int_30_40"), "/", AstFor("v2int_40_30")})); |
| 515 | |
| 516 | INSTANTIATE_TEST_SUITE_P( |
| 517 | SpvParserTest_SDiv_MixedSignednessOperands, |
| 518 | SpvBinaryArithTest, |
| 519 | ::testing::Values( |
| 520 | // Mixed, returning int, second arg uint |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 521 | BinaryData{"int", "int_30", "OpSDiv", "uint_10", "i32", "30i", "/", "bitcast<i32>(10u)"}, |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 522 | // Mixed, returning int, first arg uint |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 523 | BinaryData{"int", "uint_10", "OpSDiv", "int_30", "i32", "bitcast<i32>(10u)", "/", |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 524 | "30i"}, // Mixed, returning v2int, first arg v2uint |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 525 | BinaryData{"v2int", "v2uint_10_20", "OpSDiv", "v2int_30_40", "vec2<i32>", |
| 526 | AstFor("cast_int_v2uint_10_20"), "/", AstFor("v2int_30_40")}, |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 527 | // Mixed, returning v2int, second arg v2uint |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 528 | BinaryData{"v2int", "v2int_30_40", "OpSDiv", "v2uint_10_20", "vec2<i32>", |
| 529 | AstFor("v2int_30_40"), "/", AstFor("cast_int_v2uint_10_20")})); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 530 | |
| 531 | TEST_F(SpvBinaryArithTestBasic, SDiv_Scalar_UnsignedResult) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 532 | // The WGSL signed division operator expects both operands to be signed |
| 533 | // and the result is signed as well. |
| 534 | // In this test SPIR-V demands an unsigned result, so we have to |
| 535 | // wrap the result with an as-cast. |
| 536 | const auto assembly = Preamble() + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 537 | %100 = OpFunction %void None %voidfn |
| 538 | %entry = OpLabel |
| 539 | %1 = OpSDiv %uint %int_30 %int_40 |
| 540 | OpReturn |
| 541 | OpFunctionEnd |
| 542 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 543 | auto p = parser(test::Assemble(assembly)); |
| 544 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error() << "\n" << assembly; |
| 545 | auto fe = p->function_emitter(100); |
| 546 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 547 | auto ast_body = fe.ast_body(); |
| 548 | EXPECT_THAT(test::ToString(p->program(), ast_body), |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 549 | HasSubstr("let x_1 : u32 = bitcast<u32>((30i / 40i));")); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 550 | } |
| 551 | |
| 552 | TEST_F(SpvBinaryArithTestBasic, SDiv_Vector_UnsignedResult) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 553 | // The WGSL signed division operator expects both operands to be signed |
| 554 | // and the result is signed as well. |
| 555 | // In this test SPIR-V demands an unsigned result, so we have to |
| 556 | // wrap the result with an as-cast. |
| 557 | const auto assembly = Preamble() + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 558 | %100 = OpFunction %void None %voidfn |
| 559 | %entry = OpLabel |
| 560 | %1 = OpSDiv %v2uint %v2int_30_40 %v2int_40_30 |
| 561 | OpReturn |
| 562 | OpFunctionEnd |
| 563 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 564 | auto p = parser(test::Assemble(assembly)); |
| 565 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error() << "\n" << assembly; |
| 566 | auto fe = p->function_emitter(100); |
| 567 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 568 | auto ast_body = fe.ast_body(); |
| 569 | EXPECT_THAT( |
| 570 | test::ToString(p->program(), ast_body), |
| 571 | HasSubstr( |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 572 | R"(let x_1 : vec2<u32> = bitcast<vec2<u32>>((vec2<i32>(30i, 40i) / vec2<i32>(40i, 30i)));)")); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 573 | } |
| 574 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 575 | INSTANTIATE_TEST_SUITE_P(SpvParserTest_FDiv, |
| 576 | SpvBinaryArithTest, |
| 577 | ::testing::Values( |
| 578 | // Scalar float |
| 579 | BinaryData{"float", "float_50", "OpFDiv", "float_60", "f32", "50.0", |
| 580 | "/", "60.0"}, // Vector float |
| 581 | BinaryData{"v2float", "v2float_50_60", "OpFDiv", "v2float_60_50", |
| 582 | "vec2<f32>", AstFor("v2float_50_60"), "/", |
| 583 | AstFor("v2float_60_50")})); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 584 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 585 | INSTANTIATE_TEST_SUITE_P(SpvParserTest_UMod, |
| 586 | SpvBinaryArithTest, |
| 587 | ::testing::Values( |
| 588 | // Both uint |
| 589 | BinaryData{"uint", "uint_10", "OpUMod", "uint_20", "u32", "10u", "%", |
| 590 | "20u"}, // Both v2uint |
| 591 | BinaryData{"v2uint", "v2uint_10_20", "OpUMod", "v2uint_20_10", |
| 592 | "vec2<u32>", AstFor("v2uint_10_20"), "%", |
| 593 | AstFor("v2uint_20_10")})); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 594 | |
| 595 | // Currently WGSL is missing a mapping for OpSRem |
| 596 | // https://github.com/gpuweb/gpuweb/issues/702 |
| 597 | |
| 598 | INSTANTIATE_TEST_SUITE_P( |
| 599 | SpvParserTest_SMod, |
| 600 | SpvBinaryArithTest, |
| 601 | ::testing::Values( |
| 602 | // Both int |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 603 | BinaryData{"int", "int_30", "OpSMod", "int_40", "i32", "30i", "%", "40i"}, // Both v2int |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 604 | BinaryData{"v2int", "v2int_30_40", "OpSMod", "v2int_40_30", "vec2<i32>", |
| 605 | AstFor("v2int_30_40"), "%", AstFor("v2int_40_30")})); |
| 606 | |
| 607 | INSTANTIATE_TEST_SUITE_P( |
| 608 | SpvParserTest_SMod_MixedSignednessOperands, |
| 609 | SpvBinaryArithTest, |
| 610 | ::testing::Values( |
| 611 | // Mixed, returning int, second arg uint |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 612 | BinaryData{"int", "int_30", "OpSMod", "uint_10", "i32", "30i", "%", "bitcast<i32>(10u)"}, |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 613 | // Mixed, returning int, first arg uint |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 614 | BinaryData{"int", "uint_10", "OpSMod", "int_30", "i32", "bitcast<i32>(10u)", "%", |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 615 | "30i"}, // Mixed, returning v2int, first arg v2uint |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 616 | BinaryData{"v2int", "v2uint_10_20", "OpSMod", "v2int_30_40", "vec2<i32>", |
| 617 | AstFor("cast_int_v2uint_10_20"), "%", AstFor("v2int_30_40")}, |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 618 | // Mixed, returning v2int, second arg v2uint |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 619 | BinaryData{"v2int", "v2int_30_40", "OpSMod", "v2uint_10_20", "vec2<i32>", |
| 620 | AstFor("v2int_30_40"), "%", AstFor("cast_int_v2uint_10_20")})); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 621 | |
| 622 | TEST_F(SpvBinaryArithTestBasic, SMod_Scalar_UnsignedResult) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 623 | // The WGSL signed modulus operator expects both operands to be signed |
| 624 | // and the result is signed as well. |
| 625 | // In this test SPIR-V demands an unsigned result, so we have to |
| 626 | // wrap the result with an as-cast. |
| 627 | const auto assembly = Preamble() + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 628 | %100 = OpFunction %void None %voidfn |
| 629 | %entry = OpLabel |
| 630 | %1 = OpSMod %uint %int_30 %int_40 |
| 631 | OpReturn |
| 632 | OpFunctionEnd |
| 633 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 634 | auto p = parser(test::Assemble(assembly)); |
| 635 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error() << "\n" << assembly; |
| 636 | auto fe = p->function_emitter(100); |
| 637 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 638 | auto ast_body = fe.ast_body(); |
| 639 | EXPECT_THAT(test::ToString(p->program(), ast_body), |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 640 | HasSubstr("let x_1 : u32 = bitcast<u32>((30i % 40i));")); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 641 | } |
| 642 | |
| 643 | TEST_F(SpvBinaryArithTestBasic, SMod_Vector_UnsignedResult) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 644 | // The WGSL signed modulus operator expects both operands to be signed |
| 645 | // and the result is signed as well. |
| 646 | // In this test SPIR-V demands an unsigned result, so we have to |
| 647 | // wrap the result with an as-cast. |
| 648 | const auto assembly = Preamble() + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 649 | %100 = OpFunction %void None %voidfn |
| 650 | %entry = OpLabel |
| 651 | %1 = OpSMod %v2uint %v2int_30_40 %v2int_40_30 |
| 652 | OpReturn |
| 653 | OpFunctionEnd |
| 654 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 655 | auto p = parser(test::Assemble(assembly)); |
| 656 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error() << "\n" << assembly; |
| 657 | auto fe = p->function_emitter(100); |
| 658 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 659 | auto ast_body = fe.ast_body(); |
| 660 | EXPECT_THAT( |
| 661 | test::ToString(p->program(), ast_body), |
| 662 | HasSubstr( |
Ben Clayton | 06496d4 | 2022-05-04 22:25:19 +0000 | [diff] [blame] | 663 | R"(let x_1 : vec2<u32> = bitcast<vec2<u32>>((vec2<i32>(30i, 40i) % vec2<i32>(40i, 30i)));)")); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 664 | } |
| 665 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 666 | INSTANTIATE_TEST_SUITE_P(SpvParserTest_FRem, |
| 667 | SpvBinaryArithTest, |
| 668 | ::testing::Values( |
| 669 | // Scalar float |
| 670 | BinaryData{"float", "float_50", "OpFRem", "float_60", "f32", "50.0", |
| 671 | "%", "60.0"}, // Vector float |
| 672 | BinaryData{"v2float", "v2float_50_60", "OpFRem", "v2float_60_50", |
| 673 | "vec2<f32>", AstFor("v2float_50_60"), "%", |
| 674 | AstFor("v2float_60_50")})); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 675 | |
| 676 | TEST_F(SpvBinaryArithTestBasic, FMod_Scalar) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 677 | const auto assembly = Preamble() + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 678 | %100 = OpFunction %void None %voidfn |
| 679 | %entry = OpLabel |
| 680 | %1 = OpFMod %float %float_50 %float_60 |
| 681 | OpReturn |
| 682 | OpFunctionEnd |
| 683 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 684 | auto p = parser(test::Assemble(assembly)); |
| 685 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error() << "\n" << assembly; |
| 686 | auto fe = p->function_emitter(100); |
| 687 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 688 | auto ast_body = fe.ast_body(); |
| 689 | EXPECT_THAT(test::ToString(p->program(), ast_body), |
| 690 | HasSubstr("let x_1 : f32 = (50.0 - (60.0 * floor((50.0 / 60.0))));")); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 691 | } |
| 692 | |
| 693 | TEST_F(SpvBinaryArithTestBasic, FMod_Vector) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 694 | const auto assembly = Preamble() + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 695 | %100 = OpFunction %void None %voidfn |
| 696 | %entry = OpLabel |
| 697 | %1 = OpFMod %v2float %v2float_50_60 %v2float_60_50 |
| 698 | OpReturn |
| 699 | OpFunctionEnd |
| 700 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 701 | auto p = parser(test::Assemble(assembly)); |
| 702 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error() << "\n" << assembly; |
| 703 | auto fe = p->function_emitter(100); |
| 704 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 705 | auto ast_body = fe.ast_body(); |
| 706 | EXPECT_THAT( |
| 707 | test::ToString(p->program(), ast_body), |
| 708 | HasSubstr( |
| 709 | R"(let x_1 : vec2<f32> = (vec2<f32>(50.0, 60.0) - (vec2<f32>(60.0, 50.0) * floor((vec2<f32>(50.0, 60.0) / vec2<f32>(60.0, 50.0)))));)")); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 710 | } |
| 711 | |
| 712 | TEST_F(SpvBinaryArithTestBasic, VectorTimesScalar) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 713 | const auto assembly = Preamble() + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 714 | %100 = OpFunction %void None %voidfn |
| 715 | %entry = OpLabel |
| 716 | %1 = OpCopyObject %v2float %v2float_50_60 |
| 717 | %2 = OpCopyObject %float %float_50 |
| 718 | %10 = OpVectorTimesScalar %v2float %1 %2 |
| 719 | OpReturn |
| 720 | OpFunctionEnd |
| 721 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 722 | auto p = parser(test::Assemble(assembly)); |
| 723 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly << p->error(); |
| 724 | auto fe = p->function_emitter(100); |
| 725 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 726 | auto ast_body = fe.ast_body(); |
| 727 | EXPECT_THAT(test::ToString(p->program(), ast_body), |
| 728 | HasSubstr("let x_10 : vec2<f32> = (x_1 * x_2);")); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 729 | } |
| 730 | |
| 731 | TEST_F(SpvBinaryArithTestBasic, MatrixTimesScalar) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 732 | const auto assembly = Preamble() + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 733 | %100 = OpFunction %void None %voidfn |
| 734 | %entry = OpLabel |
| 735 | %1 = OpCopyObject %m2v2float %m2v2float_a |
| 736 | %2 = OpCopyObject %float %float_50 |
| 737 | %10 = OpMatrixTimesScalar %m2v2float %1 %2 |
| 738 | OpReturn |
| 739 | OpFunctionEnd |
| 740 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 741 | auto p = parser(test::Assemble(assembly)); |
| 742 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly << p->error(); |
| 743 | auto fe = p->function_emitter(100); |
| 744 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 745 | auto ast_body = fe.ast_body(); |
| 746 | EXPECT_THAT(test::ToString(p->program(), ast_body), |
| 747 | HasSubstr("let x_10 : mat2x2<f32> = (x_1 * x_2);")); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 748 | } |
| 749 | |
| 750 | TEST_F(SpvBinaryArithTestBasic, VectorTimesMatrix) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 751 | const auto assembly = Preamble() + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 752 | %100 = OpFunction %void None %voidfn |
| 753 | %entry = OpLabel |
| 754 | %1 = OpCopyObject %m2v2float %m2v2float_a |
| 755 | %2 = OpCopyObject %v2float %v2float_50_60 |
| 756 | %10 = OpMatrixTimesVector %v2float %1 %2 |
| 757 | OpReturn |
| 758 | OpFunctionEnd |
| 759 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 760 | auto p = parser(test::Assemble(assembly)); |
| 761 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly << p->error(); |
| 762 | auto fe = p->function_emitter(100); |
| 763 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 764 | auto ast_body = fe.ast_body(); |
| 765 | EXPECT_THAT(test::ToString(p->program(), ast_body), |
| 766 | HasSubstr("let x_10 : vec2<f32> = (x_1 * x_2);")); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 767 | } |
| 768 | |
| 769 | TEST_F(SpvBinaryArithTestBasic, MatrixTimesVector) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 770 | const auto assembly = Preamble() + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 771 | %100 = OpFunction %void None %voidfn |
| 772 | %entry = OpLabel |
| 773 | %1 = OpCopyObject %m2v2float %m2v2float_a |
| 774 | %2 = OpCopyObject %v2float %v2float_50_60 |
| 775 | %10 = OpMatrixTimesVector %v2float %1 %2 |
| 776 | OpReturn |
| 777 | OpFunctionEnd |
| 778 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 779 | auto p = parser(test::Assemble(assembly)); |
| 780 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly << p->error(); |
| 781 | auto fe = p->function_emitter(100); |
| 782 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 783 | auto ast_body = fe.ast_body(); |
| 784 | EXPECT_THAT(test::ToString(p->program(), ast_body), |
| 785 | HasSubstr("let x_10 : vec2<f32> = (x_1 * x_2);")); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 786 | } |
| 787 | |
| 788 | TEST_F(SpvBinaryArithTestBasic, MatrixTimesMatrix) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 789 | const auto assembly = Preamble() + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 790 | %100 = OpFunction %void None %voidfn |
| 791 | %entry = OpLabel |
| 792 | %1 = OpCopyObject %m2v2float %m2v2float_a |
| 793 | %2 = OpCopyObject %m2v2float %m2v2float_b |
| 794 | %10 = OpMatrixTimesMatrix %m2v2float %1 %2 |
| 795 | OpReturn |
| 796 | OpFunctionEnd |
| 797 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 798 | auto p = parser(test::Assemble(assembly)); |
| 799 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly << p->error(); |
| 800 | auto fe = p->function_emitter(100); |
| 801 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 802 | auto ast_body = fe.ast_body(); |
| 803 | EXPECT_THAT(test::ToString(p->program(), ast_body), |
| 804 | HasSubstr("let x_10 : mat2x2<f32> = (x_1 * x_2);")); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 805 | } |
| 806 | |
| 807 | TEST_F(SpvBinaryArithTestBasic, Dot) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 808 | const auto assembly = Preamble() + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 809 | %100 = OpFunction %void None %voidfn |
| 810 | %entry = OpLabel |
| 811 | %1 = OpCopyObject %v2float %v2float_50_60 |
| 812 | %2 = OpCopyObject %v2float %v2float_60_50 |
| 813 | %3 = OpDot %float %1 %2 |
| 814 | OpReturn |
| 815 | OpFunctionEnd |
| 816 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 817 | auto p = parser(test::Assemble(assembly)); |
| 818 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly << p->error(); |
| 819 | auto fe = p->function_emitter(100); |
| 820 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 821 | auto ast_body = fe.ast_body(); |
| 822 | EXPECT_THAT(test::ToString(p->program(), ast_body), |
| 823 | HasSubstr("let x_3 : f32 = dot(x_1, x_2);")); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 824 | } |
| 825 | |
| 826 | TEST_F(SpvBinaryArithTestBasic, OuterProduct) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 827 | // OpOuterProduct is expanded to basic operations. |
| 828 | // The operands, even if used once, are given their own const definitions. |
| 829 | const auto assembly = Preamble() + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 830 | %100 = OpFunction %void None %voidfn |
| 831 | %entry = OpLabel |
| 832 | %1 = OpFAdd %v3float %v3float_50_60_70 %v3float_50_60_70 ; column vector |
| 833 | %2 = OpFAdd %v2float %v2float_60_50 %v2float_50_60 ; row vector |
| 834 | %3 = OpOuterProduct %m2v3float %1 %2 |
| 835 | OpReturn |
| 836 | OpFunctionEnd |
| 837 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 838 | auto p = parser(test::Assemble(assembly)); |
| 839 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly << p->error(); |
| 840 | auto fe = p->function_emitter(100); |
| 841 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 842 | auto ast_body = fe.ast_body(); |
| 843 | auto got = test::ToString(p->program(), ast_body); |
| 844 | EXPECT_THAT(got, HasSubstr("let x_3 : mat2x3<f32> = mat2x3<f32>(" |
| 845 | "vec3<f32>((x_2.x * x_1.x), (x_2.x * x_1.y), (x_2.x * x_1.z)), " |
| 846 | "vec3<f32>((x_2.y * x_1.x), (x_2.y * x_1.y), (x_2.y * x_1.z)));")) |
| 847 | << got; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 848 | } |
| 849 | |
| 850 | struct BuiltinData { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 851 | const std::string spirv; |
| 852 | const std::string wgsl; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 853 | }; |
| 854 | inline std::ostream& operator<<(std::ostream& out, BuiltinData data) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 855 | out << "OpData{" << data.spirv << "," << data.wgsl << "}"; |
| 856 | return out; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 857 | } |
| 858 | struct ArgAndTypeData { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 859 | const std::string spirv_type; |
| 860 | const std::string spirv_arg; |
| 861 | const std::string ast_type; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 862 | }; |
| 863 | inline std::ostream& operator<<(std::ostream& out, ArgAndTypeData data) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 864 | out << "ArgAndTypeData{" << data.spirv_type << "," << data.spirv_arg << "," << data.ast_type |
| 865 | << "}"; |
| 866 | return out; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 867 | } |
| 868 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 869 | using SpvBinaryDerivativeTest = |
| 870 | SpvParserTestBase<::testing::TestWithParam<std::tuple<BuiltinData, ArgAndTypeData>>>; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 871 | |
| 872 | TEST_P(SpvBinaryDerivativeTest, Derivatives) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 873 | auto& builtin = std::get<0>(GetParam()); |
| 874 | auto& arg = std::get<1>(GetParam()); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 875 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 876 | const auto assembly = R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 877 | OpCapability DerivativeControl |
| 878 | )" + Preamble() + R"( |
| 879 | %100 = OpFunction %void None %voidfn |
| 880 | %entry = OpLabel |
| 881 | %1 = OpCopyObject %)" + |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 882 | arg.spirv_type + " %" + arg.spirv_arg + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 883 | %2 = )" + builtin.spirv + |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 884 | " %" + arg.spirv_type + R"( %1 |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 885 | OpReturn |
| 886 | OpFunctionEnd |
| 887 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 888 | auto p = parser(test::Assemble(assembly)); |
| 889 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly << p->error(); |
| 890 | auto fe = p->function_emitter(100); |
| 891 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 892 | auto ast_body = fe.ast_body(); |
| 893 | EXPECT_THAT(test::ToString(p->program(), ast_body), |
| 894 | HasSubstr("let x_2 : " + arg.ast_type + " = " + builtin.wgsl + "(x_1);")); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 895 | } |
| 896 | |
| 897 | INSTANTIATE_TEST_SUITE_P( |
| 898 | SpvBinaryDerivativeTest, |
| 899 | SpvBinaryDerivativeTest, |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 900 | testing::Combine(::testing::Values(BuiltinData{"OpDPdx", "dpdx"}, |
| 901 | BuiltinData{"OpDPdy", "dpdy"}, |
| 902 | BuiltinData{"OpFwidth", "fwidth"}, |
| 903 | BuiltinData{"OpDPdxFine", "dpdxFine"}, |
| 904 | BuiltinData{"OpDPdyFine", "dpdyFine"}, |
| 905 | BuiltinData{"OpFwidthFine", "fwidthFine"}, |
| 906 | BuiltinData{"OpDPdxCoarse", "dpdxCoarse"}, |
| 907 | BuiltinData{"OpDPdyCoarse", "dpdyCoarse"}, |
| 908 | BuiltinData{"OpFwidthCoarse", "fwidthCoarse"}), |
| 909 | ::testing::Values(ArgAndTypeData{"float", "float_50", "f32"}, |
| 910 | ArgAndTypeData{"v2float", "v2float_50_60", "vec2<f32>"}, |
| 911 | ArgAndTypeData{"v3float", "v3float_50_60_70", |
| 912 | "vec3<f32>"}))); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 913 | |
| 914 | TEST_F(SpvUnaryArithTest, Transpose_2x2) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 915 | const auto assembly = Preamble() + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 916 | %100 = OpFunction %void None %voidfn |
| 917 | %entry = OpLabel |
| 918 | %1 = OpCopyObject %m2v2float %m2v2float_a |
| 919 | %2 = OpTranspose %m2v2float %1 |
| 920 | OpReturn |
| 921 | OpFunctionEnd |
| 922 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 923 | auto p = parser(test::Assemble(assembly)); |
| 924 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error() << "\n" << assembly; |
| 925 | auto fe = p->function_emitter(100); |
| 926 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 927 | const auto* expected = "let x_2 : mat2x2<f32> = transpose(x_1);"; |
| 928 | auto ast_body = fe.ast_body(); |
| 929 | const auto got = test::ToString(p->program(), ast_body); |
| 930 | EXPECT_THAT(got, HasSubstr(expected)) << got; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 931 | } |
| 932 | |
| 933 | TEST_F(SpvUnaryArithTest, Transpose_2x3) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 934 | const auto assembly = Preamble() + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 935 | %100 = OpFunction %void None %voidfn |
| 936 | %entry = OpLabel |
| 937 | %1 = OpCopyObject %m2v3float %m2v3float_a |
| 938 | %2 = OpTranspose %m3v2float %1 |
| 939 | OpReturn |
| 940 | OpFunctionEnd |
| 941 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 942 | auto p = parser(test::Assemble(assembly)); |
| 943 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error() << "\n" << assembly; |
| 944 | auto fe = p->function_emitter(100); |
| 945 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 946 | // Note, in the AST dump mat_2_3 means 2 rows and 3 columns. |
| 947 | // So the column vectors have 2 elements. |
| 948 | // That is, %m3v2float is __mat_2_3f32. |
| 949 | const auto* expected = "let x_2 : mat3x2<f32> = transpose(x_1);"; |
| 950 | auto ast_body = fe.ast_body(); |
| 951 | const auto got = test::ToString(p->program(), ast_body); |
| 952 | EXPECT_THAT(got, HasSubstr(expected)) << got; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 953 | } |
| 954 | |
| 955 | TEST_F(SpvUnaryArithTest, Transpose_3x2) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 956 | const auto assembly = Preamble() + R"( |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 957 | %100 = OpFunction %void None %voidfn |
| 958 | %entry = OpLabel |
| 959 | %1 = OpCopyObject %m3v2float %m3v2float_a |
| 960 | %2 = OpTranspose %m2v3float %1 |
| 961 | OpReturn |
| 962 | OpFunctionEnd |
| 963 | )"; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 964 | auto p = parser(test::Assemble(assembly)); |
| 965 | ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error() << "\n" << assembly; |
| 966 | auto fe = p->function_emitter(100); |
| 967 | EXPECT_TRUE(fe.EmitBody()) << p->error(); |
| 968 | const auto* expected = "let x_2 : mat2x3<f32> = transpose(x_1);"; |
| 969 | auto ast_body = fe.ast_body(); |
| 970 | const auto got = test::ToString(p->program(), ast_body); |
| 971 | EXPECT_THAT(got, HasSubstr(expected)) << got; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 972 | } |
| 973 | |
| 974 | // TODO(dneto): OpSRem. Missing from WGSL |
| 975 | // https://github.com/gpuweb/gpuweb/issues/702 |
| 976 | |
| 977 | // TODO(dneto): OpFRem. Missing from WGSL |
| 978 | // https://github.com/gpuweb/gpuweb/issues/702 |
| 979 | |
| 980 | // TODO(dneto): OpIAddCarry |
| 981 | // TODO(dneto): OpISubBorrow |
| 982 | // TODO(dneto): OpUMulExtended |
| 983 | // TODO(dneto): OpSMulExtended |
| 984 | |
| 985 | } // namespace |
dan sinclair | 258cbaf | 2022-04-07 19:01:25 +0000 | [diff] [blame] | 986 | } // namespace tint::reader::spirv |