• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Amber 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 parseried.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "gtest/gtest.h"
16 #include "src/amberscript/parser.h"
17 
18 namespace amber {
19 namespace amberscript {
20 
21 using AmberScriptParserTest = testing::Test;
22 
TEST_F(AmberScriptParserTest,PipelineWithUnknownShader)23 TEST_F(AmberScriptParserTest, PipelineWithUnknownShader) {
24   std::string in = R"(
25 PIPELINE graphics my_pipeline
26   ATTACH my_shader
27 END)";
28 
29   Parser parser;
30   Result r = parser.Parse(in);
31   ASSERT_FALSE(r.IsSuccess());
32   EXPECT_EQ("3: unknown shader in ATTACH command", r.Error());
33 }
34 
TEST_F(AmberScriptParserTest,DuplicateShadersInAPipeline)35 TEST_F(AmberScriptParserTest, DuplicateShadersInAPipeline) {
36   std::string in = R"(
37 SHADER vertex my_shader PASSTHROUGH
38 PIPELINE graphics my_pipeline
39   ATTACH my_shader
40   ATTACH my_shader
41 END)";
42 
43   Parser parser;
44   Result r = parser.Parse(in);
45   ASSERT_FALSE(r.IsSuccess());
46   EXPECT_EQ("6: can not add duplicate shader to pipeline", r.Error());
47 }
48 
TEST_F(AmberScriptParserTest,AttachInvalidToken)49 TEST_F(AmberScriptParserTest, AttachInvalidToken) {
50   std::string in = R"(PIPELINE graphics my_pipeline
51   ATTACH 1234
52 END)";
53 
54   Parser parser;
55   Result r = parser.Parse(in);
56   ASSERT_FALSE(r.IsSuccess());
57   EXPECT_EQ("2: invalid token in ATTACH command", r.Error());
58 }
59 
TEST_F(AmberScriptParserTest,AttachExtraParameter)60 TEST_F(AmberScriptParserTest, AttachExtraParameter) {
61   std::string in = R"(
62 SHADER vertex my_shader PASSTHROUGH
63 PIPELINE graphics my_pipeline
64   ATTACH my_shader INVALID
65 END)";
66 
67   Parser parser;
68   Result r = parser.Parse(in);
69   ASSERT_FALSE(r.IsSuccess());
70   EXPECT_EQ("4: unknown ATTACH parameter: INVALID", r.Error());
71 }
72 
TEST_F(AmberScriptParserTest,AttachMissingValue)73 TEST_F(AmberScriptParserTest, AttachMissingValue) {
74   std::string in = R"(
75 SHADER vertex my_shader PASSTHROUGH
76 PIPELINE graphics my_pipeline
77   ATTACH
78 END)";
79 
80   Parser parser;
81   Result r = parser.Parse(in);
82   ASSERT_FALSE(r.IsSuccess());
83   EXPECT_EQ("5: invalid token in ATTACH command", r.Error());
84 }
85 
TEST_F(AmberScriptParserTest,ComputeShaderInGraphicsPipeline)86 TEST_F(AmberScriptParserTest, ComputeShaderInGraphicsPipeline) {
87   std::string in = R"(SHADER compute my_shader GLSL
88 void main() {
89   gl_FragColor = vec3(2, 3, 4);
90 }
91 END
92 
93 PIPELINE graphics my_pipeline
94   ATTACH my_shader
95 END)";
96 
97   Parser parser;
98   Result r = parser.Parse(in);
99   ASSERT_FALSE(r.IsSuccess()) << r.Error();
100   EXPECT_EQ("9: can not add a compute shader to a graphics pipeline",
101             r.Error());
102 }
103 
104 struct ShaderTypeData {
105   const char* name;
106   ShaderType type;
107 };
108 
109 using AmberScriptParserPipelineAttachTest =
110     testing::TestWithParam<ShaderTypeData>;
TEST_P(AmberScriptParserPipelineAttachTest,GraphicsShaderInComputePipeline)111 TEST_P(AmberScriptParserPipelineAttachTest, GraphicsShaderInComputePipeline) {
112   auto test_data = GetParam();
113 
114   std::string in = "SHADER " + std::string(test_data.name) + R"( my_shader GLSL
115 void main() {
116   gl_FragColor = vec3(2, 3, 4);
117 }
118 END
119 
120 PIPELINE compute my_pipeline
121   ATTACH my_shader
122 END)";
123 
124   Parser parser;
125   Result r = parser.Parse(in);
126   ASSERT_FALSE(r.IsSuccess()) << r.Error();
127   EXPECT_EQ("9: only compute shaders allowed in a compute pipeline", r.Error());
128 }
129 INSTANTIATE_TEST_SUITE_P(
130     AmberScriptParserPipelineAttachTests,
131     AmberScriptParserPipelineAttachTest,
132     testing::Values(
133         ShaderTypeData{"vertex", kShaderTypeVertex},
134         ShaderTypeData{"fragment", kShaderTypeFragment},
135         ShaderTypeData{"geometry", kShaderTypeGeometry},
136         ShaderTypeData{"tessellation_evaluation",
137                        kShaderTypeTessellationEvaluation},
138         ShaderTypeData{
139             "tessellation_control",
140             kShaderTypeTessellationControl}));  // NOLINT(whitespace/parens)
141 
TEST_F(AmberScriptParserTest,PipelineEntryPoint)142 TEST_F(AmberScriptParserTest, PipelineEntryPoint) {
143   std::string in = R"(
144 SHADER vertex my_shader PASSTHROUGH
145 SHADER fragment my_fragment GLSL
146 # GLSL Shader
147 END
148 
149 PIPELINE graphics my_pipeline
150   ATTACH my_shader ENTRY_POINT green
151   ATTACH my_fragment
152 END
153 )";
154 
155   Parser parser;
156   Result r = parser.Parse(in);
157   ASSERT_TRUE(r.IsSuccess()) << r.Error();
158 
159   auto script = parser.GetScript();
160   const auto& pipelines = script->GetPipelines();
161   ASSERT_EQ(1U, pipelines.size());
162 
163   const auto* pipeline = pipelines[0].get();
164   const auto& shaders = pipeline->GetShaders();
165   ASSERT_EQ(2U, shaders.size());
166 
167   ASSERT_TRUE(shaders[0].GetShader() != nullptr);
168   EXPECT_EQ(kShaderTypeVertex, shaders[0].GetShader()->GetType());
169   EXPECT_EQ("green", shaders[0].GetEntryPoint());
170 
171   ASSERT_TRUE(shaders[1].GetShader() != nullptr);
172   EXPECT_EQ(kShaderTypeFragment, shaders[1].GetShader()->GetType());
173   EXPECT_EQ("main", shaders[1].GetEntryPoint());
174 }
175 
TEST_F(AmberScriptParserTest,PipelineEntryPointWithInvalidValue)176 TEST_F(AmberScriptParserTest, PipelineEntryPointWithInvalidValue) {
177   std::string in = R"(
178 SHADER compute my_compute GLSL
179 # Compute Shader
180 END
181 PIPELINE compute my_pipeline
182   ATTACH my_compute ENTRY_POINT 1234
183 END)";
184 
185   Parser parser;
186   Result r = parser.Parse(in);
187   ASSERT_FALSE(r.IsSuccess());
188   EXPECT_EQ("6: missing shader name in ATTACH ENTRY_POINT command", r.Error());
189 }
190 
TEST_F(AmberScriptParserTest,PipelineEntryPointMissingValue)191 TEST_F(AmberScriptParserTest, PipelineEntryPointMissingValue) {
192   std::string in = R"(
193 SHADER compute my_compute GLSL
194 # Compute Shader
195 END
196 PIPELINE compute my_pipeline
197   ATTACH my_compute ENTRY_POINT
198 END)";
199 
200   Parser parser;
201   Result r = parser.Parse(in);
202   ASSERT_FALSE(r.IsSuccess());
203   EXPECT_EQ("7: missing shader name in ATTACH ENTRY_POINT command", r.Error());
204 }
205 
TEST_F(AmberScriptParserTest,PipelineEntryPointExtraParameter)206 TEST_F(AmberScriptParserTest, PipelineEntryPointExtraParameter) {
207   std::string in = R"(
208 SHADER compute my_compute GLSL
209 # Compute Shader
210 END
211 PIPELINE compute my_pipeline
212   ATTACH my_compute ENTRY_POINT green INVALID
213 END)";
214 
215   Parser parser;
216   Result r = parser.Parse(in);
217   ASSERT_FALSE(r.IsSuccess());
218   EXPECT_EQ("6: unknown ATTACH parameter: INVALID", r.Error());
219 }
220 
TEST_F(AmberScriptParserTest,PiplineMultiShaderAttach)221 TEST_F(AmberScriptParserTest, PiplineMultiShaderAttach) {
222   std::string in = R"(
223 SHADER multi my_shader GLSL
224 # shaders
225 END
226 PIPELINE compute my_pipeline
227   ATTACH my_shader TYPE compute ENTRY_POINT my_entry_point
228 END)";
229 
230   Parser parser;
231   Result r = parser.Parse(in);
232   ASSERT_TRUE(r.IsSuccess()) << r.Error();
233 
234   auto script = parser.GetScript();
235   const auto& pipelines = script->GetPipelines();
236   ASSERT_EQ(1U, pipelines.size());
237 
238   const auto* pipeline = pipelines[0].get();
239   const auto& shaders = pipeline->GetShaders();
240   ASSERT_EQ(1U, shaders.size());
241 
242   ASSERT_TRUE(shaders[0].GetShader() != nullptr);
243   EXPECT_EQ(kShaderTypeMulti, shaders[0].GetShader()->GetType());
244   EXPECT_EQ(kShaderTypeCompute, shaders[0].GetShaderType());
245   EXPECT_EQ("my_entry_point", shaders[0].GetEntryPoint());
246 }
247 
TEST_F(AmberScriptParserTest,PipelineMultiShaderMismatchPipelineAndShaderType)248 TEST_F(AmberScriptParserTest,
249        PipelineMultiShaderMismatchPipelineAndShaderType) {
250   std::string in = R"(
251 SHADER multi my_shader GLSL
252 # shaders
253 END
254 PIPELINE graphics my_pipeline
255   ATTACH my_shader TYPE compute ENTRY_POINT my_entry_point
256 END)";
257 
258   Parser parser;
259   Result r = parser.Parse(in);
260   ASSERT_FALSE(r.IsSuccess());
261   EXPECT_EQ("6: can not add a compute shader to a graphics pipeline",
262             r.Error());
263 }
264 
TEST_F(AmberScriptParserTest,PipelineMultiShaderMissingEntryPoint)265 TEST_F(AmberScriptParserTest, PipelineMultiShaderMissingEntryPoint) {
266   std::string in = R"(
267 SHADER multi my_shader GLSL
268 # shaders
269 END
270 PIPELINE graphics my_pipeline
271   ATTACH my_shader TYPE fragment
272 END)";
273 
274   Parser parser;
275   Result r = parser.Parse(in);
276   ASSERT_FALSE(r.IsSuccess());
277   EXPECT_EQ("7: ATTACH TYPE requires an ENTRY_POINT", r.Error());
278 }
279 
TEST_F(AmberScriptParserTest,PipelineMultiShaderMissingType)280 TEST_F(AmberScriptParserTest, PipelineMultiShaderMissingType) {
281   std::string in = R"(
282 SHADER multi my_shader GLSL
283 # shaders
284 END
285 PIPELINE graphics my_pipeline
286   ATTACH my_shader
287 END)";
288 
289   Parser parser;
290   Result r = parser.Parse(in);
291   ASSERT_FALSE(r.IsSuccess());
292   EXPECT_EQ("7: multi shader ATTACH requires TYPE", r.Error());
293 }
294 
TEST_F(AmberScriptParserTest,PipelineMultiShaderMissingTypeWithEntryPoint)295 TEST_F(AmberScriptParserTest, PipelineMultiShaderMissingTypeWithEntryPoint) {
296   std::string in = R"(
297 SHADER multi my_shader GLSL
298 # shaders
299 END
300 PIPELINE graphics my_pipeline
301   ATTACH my_shader ENTRY_POINT my_ep
302 END)";
303 
304   Parser parser;
305   Result r = parser.Parse(in);
306   ASSERT_FALSE(r.IsSuccess());
307   EXPECT_EQ("6: ATTACH missing TYPE for multi shader", r.Error());
308 }
309 
TEST_F(AmberScriptParserTest,PipelineSpecializationUint32)310 TEST_F(AmberScriptParserTest, PipelineSpecializationUint32) {
311   std::string in = R"(
312 SHADER compute my_shader GLSL
313 #shaders
314 END
315 PIPELINE compute my_pipeline
316   ATTACH my_shader TYPE compute ENTRY_POINT my_ep SPECIALIZE 1 AS uint32 4
317 END)";
318 
319   Parser parser;
320   Result r = parser.Parse(in);
321   EXPECT_EQ(r.Error(), "");
322   ASSERT_TRUE(r.IsSuccess());
323 
324   auto script = parser.GetScript();
325   const auto& pipelines = script->GetPipelines();
326   ASSERT_EQ(1U, pipelines.size());
327 
328   const auto* pipeline = pipelines[0].get();
329   const auto& shaders = pipeline->GetShaders();
330   ASSERT_EQ(1U, shaders.size());
331 
332   EXPECT_EQ(1u, shaders[0].GetSpecialization().size());
333   EXPECT_EQ(4u, shaders[0].GetSpecialization().at(1));
334 }
335 
TEST_F(AmberScriptParserTest,PipelineSpecializationInt32)336 TEST_F(AmberScriptParserTest, PipelineSpecializationInt32) {
337   std::string in = R"(
338 SHADER compute my_shader GLSL
339 #shaders
340 END
341 PIPELINE compute my_pipeline
342   ATTACH my_shader TYPE compute ENTRY_POINT my_ep SPECIALIZE 2 AS int32 -1
343 END)";
344 
345   Parser parser;
346   Result r = parser.Parse(in);
347   ASSERT_TRUE(r.IsSuccess());
348 
349   auto script = parser.GetScript();
350   const auto& pipelines = script->GetPipelines();
351   ASSERT_EQ(1U, pipelines.size());
352 
353   const auto* pipeline = pipelines[0].get();
354   const auto& shaders = pipeline->GetShaders();
355   ASSERT_EQ(1U, shaders.size());
356 
357   EXPECT_EQ(1u, shaders[0].GetSpecialization().size());
358   EXPECT_EQ(0xffffffffu, shaders[0].GetSpecialization().at(2));
359 }
360 
TEST_F(AmberScriptParserTest,PipelineSpecializationFloat)361 TEST_F(AmberScriptParserTest, PipelineSpecializationFloat) {
362   std::string in = R"(
363 SHADER compute my_shader GLSL
364 #shaders
365 END
366 PIPELINE compute my_pipeline
367   ATTACH my_shader TYPE compute ENTRY_POINT my_ep SPECIALIZE 3 AS float 1.1
368 END)";
369 
370   Parser parser;
371   Result r = parser.Parse(in);
372   ASSERT_TRUE(r.IsSuccess());
373 
374   auto script = parser.GetScript();
375   const auto& pipelines = script->GetPipelines();
376   ASSERT_EQ(1U, pipelines.size());
377 
378   const auto* pipeline = pipelines[0].get();
379   const auto& shaders = pipeline->GetShaders();
380   ASSERT_EQ(1U, shaders.size());
381 
382   EXPECT_EQ(1u, shaders[0].GetSpecialization().size());
383   EXPECT_EQ(0x3f8ccccdu, shaders[0].GetSpecialization().at(3));
384 }
385 
TEST_F(AmberScriptParserTest,PipelineSpecializationIDIsString)386 TEST_F(AmberScriptParserTest, PipelineSpecializationIDIsString) {
387   std::string in = R"(
388 SHADER compute my_shader GLSL
389 #shaders
390 END
391 PIPELINE compute my_pipeline
392   ATTACH my_shader TYPE compute ENTRY_POINT my_ep SPECIALIZE s3 AS float 1.1
393 END)";
394 
395   Parser parser;
396   Result r = parser.Parse(in);
397   ASSERT_FALSE(r.IsSuccess());
398   EXPECT_EQ("6: specialization ID must be an integer", r.Error());
399 }
400 
TEST_F(AmberScriptParserTest,PipelineSpecializationNoAS)401 TEST_F(AmberScriptParserTest, PipelineSpecializationNoAS) {
402   std::string in = R"(
403 SHADER compute my_shader GLSL
404 #shaders
405 END
406 PIPELINE compute my_pipeline
407   ATTACH my_shader TYPE compute ENTRY_POINT my_ep SPECIALIZE 1 ASa float 1.1
408 END)";
409 
410   Parser parser;
411   Result r = parser.Parse(in);
412   ASSERT_FALSE(r.IsSuccess());
413   EXPECT_EQ("6: expected AS as next token", r.Error());
414 }
415 
TEST_F(AmberScriptParserTest,PipelineSpecializationNotDataType)416 TEST_F(AmberScriptParserTest, PipelineSpecializationNotDataType) {
417   std::string in = R"(
418 SHADER compute my_shader GLSL
419 #shaders
420 END
421 PIPELINE compute my_pipeline
422   ATTACH my_shader TYPE compute ENTRY_POINT my_ep SPECIALIZE 1 AS uint 1.1
423 END)";
424 
425   Parser parser;
426   Result r = parser.Parse(in);
427   ASSERT_FALSE(r.IsSuccess());
428   EXPECT_EQ("6: invalid data type 'uint' provided", r.Error());
429 }
430 
TEST_F(AmberScriptParserTest,PipelineSpecializationBadDataType)431 TEST_F(AmberScriptParserTest, PipelineSpecializationBadDataType) {
432   std::string in = R"(
433 SHADER compute my_shader GLSL
434 #shaders
435 END
436 PIPELINE compute my_pipeline
437   ATTACH my_shader ENTRY_POINT my_ep SPECIALIZE 1 AS uint8 1.1
438 END)";
439 
440   Parser parser;
441   Result r = parser.Parse(in);
442   ASSERT_FALSE(r.IsSuccess());
443   EXPECT_EQ(
444       "6: only 32-bit types are currently accepted for specialization values",
445       r.Error());
446 }
447 
TEST_F(AmberScriptParserTest,PipelineSpecializationMultipleSpecializations)448 TEST_F(AmberScriptParserTest, PipelineSpecializationMultipleSpecializations) {
449   std::string in = R"(
450 SHADER compute my_shader GLSL
451 #shaders
452 END
453 PIPELINE compute my_pipeline
454   ATTACH my_shader TYPE compute ENTRY_POINT my_ep \
455       SPECIALIZE 1 AS uint32 4 \
456       SPECIALIZE 2 AS uint32 5 \
457       SPECIALIZE 5 AS uint32 1
458 END)";
459 
460   Parser parser;
461   Result r = parser.Parse(in);
462   ASSERT_TRUE(r.IsSuccess());
463 
464   auto script = parser.GetScript();
465   const auto& pipelines = script->GetPipelines();
466   ASSERT_EQ(1U, pipelines.size());
467 
468   const auto* pipeline = pipelines[0].get();
469   const auto& shaders = pipeline->GetShaders();
470   ASSERT_EQ(1U, shaders.size());
471 
472   EXPECT_EQ(3u, shaders[0].GetSpecialization().size());
473   EXPECT_EQ(4u, shaders[0].GetSpecialization().at(1));
474   EXPECT_EQ(5u, shaders[0].GetSpecialization().at(2));
475   EXPECT_EQ(1u, shaders[0].GetSpecialization().at(5));
476 }
477 
TEST_F(AmberScriptParserTest,PipelineSpecializationNoType)478 TEST_F(AmberScriptParserTest, PipelineSpecializationNoType) {
479   std::string in = R"(
480 SHADER compute my_shader GLSL
481 #shaders
482 END
483 PIPELINE compute my_pipeline
484   ATTACH my_shader SPECIALIZE 1 AS uint32 4
485 END)";
486 
487   Parser parser;
488   Result r = parser.Parse(in);
489   ASSERT_TRUE(r.IsSuccess());
490 
491   auto script = parser.GetScript();
492   const auto& pipelines = script->GetPipelines();
493   ASSERT_EQ(1U, pipelines.size());
494 
495   const auto* pipeline = pipelines[0].get();
496   const auto& shaders = pipeline->GetShaders();
497   ASSERT_EQ(1U, shaders.size());
498 
499   EXPECT_EQ(1u, shaders[0].GetSpecialization().size());
500   EXPECT_EQ(4u, shaders[0].GetSpecialization().at(1));
501 }
502 
503 }  // namespace amberscript
504 }  // namespace amber
505