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,BindColorBuffer)23 TEST_F(AmberScriptParserTest, BindColorBuffer) {
24   std::string in = R"(
25 SHADER vertex my_shader PASSTHROUGH
26 SHADER fragment my_fragment GLSL
27 # GLSL Shader
28 END
29 BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
30 
31 PIPELINE graphics my_pipeline
32   ATTACH my_shader
33   ATTACH my_fragment
34 
35   BIND BUFFER my_fb AS color LOCATION 0
36 END)";
37 
38   Parser parser;
39   Result r = parser.Parse(in);
40   ASSERT_TRUE(r.IsSuccess()) << r.Error();
41 
42   auto script = parser.GetScript();
43   const auto& pipelines = script->GetPipelines();
44   ASSERT_EQ(1U, pipelines.size());
45 
46   const auto* pipeline = pipelines[0].get();
47   const auto& color_buffers = pipeline->GetColorAttachments();
48   ASSERT_EQ(1U, color_buffers.size());
49 
50   const auto& buf_info = color_buffers[0];
51   ASSERT_TRUE(buf_info.buffer != nullptr);
52   EXPECT_EQ(0u, buf_info.location);
53   EXPECT_EQ(250u * 250u, buf_info.buffer->ElementCount());
54   EXPECT_EQ(250u * 250u * 4u, buf_info.buffer->ValueCount());
55   EXPECT_EQ(250u * 250u * 4u * sizeof(float),
56             buf_info.buffer->GetSizeInBytes());
57 }
58 
TEST_F(AmberScriptParserTest,BindColorBufferTwice)59 TEST_F(AmberScriptParserTest, BindColorBufferTwice) {
60   std::string in = R"(
61 SHADER vertex my_shader PASSTHROUGH
62 SHADER fragment my_fragment GLSL
63 # GLSL Shader
64 END
65 BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
66 
67 PIPELINE graphics my_pipeline
68   ATTACH my_shader
69   ATTACH my_fragment
70 
71   BIND BUFFER my_fb AS color LOCATION 0
72   BIND BUFFER my_fb AS color LOCATION 1
73 END)";
74 
75   Parser parser;
76   Result r = parser.Parse(in);
77   ASSERT_FALSE(r.IsSuccess());
78   EXPECT_EQ("13: color buffer may only be bound to a PIPELINE once", r.Error());
79 }
80 
TEST_F(AmberScriptParserTest,BindColorBufferMissingBuffer)81 TEST_F(AmberScriptParserTest, BindColorBufferMissingBuffer) {
82   std::string in = R"(
83 SHADER vertex my_shader PASSTHROUGH
84 SHADER fragment my_fragment GLSL
85 # GLSL Shader
86 END
87 BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
88 
89 PIPELINE graphics my_pipeline
90   ATTACH my_shader
91   ATTACH my_fragment
92 
93   BIND BUFFER AS color LOCATION 0
94 END)";
95 
96   Parser parser;
97   Result r = parser.Parse(in);
98   ASSERT_FALSE(r.IsSuccess());
99   EXPECT_EQ("12: unknown buffer: AS", r.Error());
100 }
101 
TEST_F(AmberScriptParserTest,BindColorBufferNonDeclaredBuffer)102 TEST_F(AmberScriptParserTest, BindColorBufferNonDeclaredBuffer) {
103   std::string in = R"(
104 SHADER vertex my_shader PASSTHROUGH
105 SHADER fragment my_fragment GLSL
106 # GLSL Shader
107 END
108 
109 PIPELINE graphics my_pipeline
110   ATTACH my_shader
111   ATTACH my_fragment
112 
113   BIND BUFFER my_fb AS color LOCATION 0
114 END)";
115 
116   Parser parser;
117   Result r = parser.Parse(in);
118   ASSERT_FALSE(r.IsSuccess());
119   EXPECT_EQ("11: unknown buffer: my_fb", r.Error());
120 }
121 
TEST_F(AmberScriptParserTest,BindColorBufferMissingLocation)122 TEST_F(AmberScriptParserTest, BindColorBufferMissingLocation) {
123   std::string in = R"(
124 SHADER vertex my_shader PASSTHROUGH
125 SHADER fragment my_fragment GLSL
126 # GLSL Shader
127 END
128 BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
129 
130 PIPELINE graphics my_pipeline
131   ATTACH my_shader
132   ATTACH my_fragment
133 
134   BIND BUFFER my_fb AS color
135 END)";
136 
137   Parser parser;
138   Result r = parser.Parse(in);
139   ASSERT_FALSE(r.IsSuccess());
140   EXPECT_EQ("13: BIND missing LOCATION", r.Error());
141 }
142 
TEST_F(AmberScriptParserTest,BindColorBufferMissingLocationIndex)143 TEST_F(AmberScriptParserTest, BindColorBufferMissingLocationIndex) {
144   std::string in = R"(
145 SHADER vertex my_shader PASSTHROUGH
146 SHADER fragment my_fragment GLSL
147 # GLSL Shader
148 END
149 BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
150 
151 PIPELINE graphics my_pipeline
152   ATTACH my_shader
153   ATTACH my_fragment
154 
155   BIND BUFFER my_fb AS color LOCATION
156 END)";
157 
158   Parser parser;
159   Result r = parser.Parse(in);
160   ASSERT_FALSE(r.IsSuccess());
161   EXPECT_EQ("13: invalid value for BIND LOCATION", r.Error());
162 }
163 
TEST_F(AmberScriptParserTest,BindColorBufferInvalidLocationIndex)164 TEST_F(AmberScriptParserTest, BindColorBufferInvalidLocationIndex) {
165   std::string in = R"(
166 SHADER vertex my_shader PASSTHROUGH
167 SHADER fragment my_fragment GLSL
168 # GLSL Shader
169 END
170 BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
171 
172 PIPELINE graphics my_pipeline
173   ATTACH my_shader
174   ATTACH my_fragment
175 
176   BIND BUFFER my_fb AS color LOCATION INVALID
177 END)";
178 
179   Parser parser;
180   Result r = parser.Parse(in);
181   ASSERT_FALSE(r.IsSuccess());
182   EXPECT_EQ("12: invalid value for BIND LOCATION", r.Error());
183 }
184 
TEST_F(AmberScriptParserTest,BindColorBufferExtraParams)185 TEST_F(AmberScriptParserTest, BindColorBufferExtraParams) {
186   std::string in = R"(
187 SHADER vertex my_shader PASSTHROUGH
188 SHADER fragment my_fragment GLSL
189 # GLSL Shader
190 END
191 BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
192 
193 PIPELINE graphics my_pipeline
194   ATTACH my_shader
195   ATTACH my_fragment
196 
197   BIND BUFFER my_fb AS color LOCATION 0 EXTRA
198 END)";
199 
200   Parser parser;
201   Result r = parser.Parse(in);
202   ASSERT_FALSE(r.IsSuccess());
203   EXPECT_EQ("12: extra parameters after BIND command: EXTRA", r.Error());
204 }
205 
TEST_F(AmberScriptParserTest,BindColorBufferDuplicateLocation)206 TEST_F(AmberScriptParserTest, BindColorBufferDuplicateLocation) {
207   std::string in = R"(
208 SHADER vertex my_shader PASSTHROUGH
209 SHADER fragment my_fragment GLSL
210 # GLSL Shader
211 END
212 BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
213 BUFFER sec_fb FORMAT R32G32B32A32_SFLOAT
214 
215 PIPELINE graphics my_pipeline
216   ATTACH my_shader
217   ATTACH my_fragment
218 
219   BIND BUFFER my_fb AS color LOCATION 0
220   BIND BUFFER sec_fb AS color LOCATION 0
221 END)";
222 
223   Parser parser;
224   Result r = parser.Parse(in);
225   ASSERT_FALSE(r.IsSuccess());
226   EXPECT_EQ("14: can not bind two color buffers to the same LOCATION",
227             r.Error());
228 }
229 
TEST_F(AmberScriptParserTest,BindColorToTwoPipelinesRequiresMatchingSize)230 TEST_F(AmberScriptParserTest, BindColorToTwoPipelinesRequiresMatchingSize) {
231   std::string in = R"(
232 SHADER vertex my_shader PASSTHROUGH
233 SHADER fragment my_fragment GLSL
234 # GLSL Shader
235 END
236 BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
237 
238 PIPELINE graphics my_pipeline
239   ATTACH my_shader
240   ATTACH my_fragment
241 
242   BIND BUFFER my_fb AS color LOCATION 0
243 END
244 PIPELINE graphics second_pipeline
245   ATTACH my_shader
246   ATTACH my_fragment
247 
248   BIND BUFFER my_fb AS color LOCATION 0
249   FRAMEBUFFER_SIZE 256 300
250 END)";
251 
252   Parser parser;
253   Result r = parser.Parse(in);
254   ASSERT_FALSE(r.IsSuccess());
255   EXPECT_EQ("shared framebuffer must have same size over all PIPELINES",
256             r.Error());
257 }
258 
TEST_F(AmberScriptParserTest,BindColorTwoPipelines)259 TEST_F(AmberScriptParserTest, BindColorTwoPipelines) {
260   std::string in = R"(
261 SHADER vertex my_shader PASSTHROUGH
262 SHADER fragment my_fragment GLSL
263 # GLSL Shader
264 END
265 BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
266 BUFFER second_fb FORMAT R8G8B8A8_UINT
267 BUFFER depth_1 FORMAT D32_SFLOAT_S8_UINT
268 BUFFER depth_2 FORMAT D32_SFLOAT_S8_UINT
269 
270 PIPELINE graphics my_pipeline
271   ATTACH my_shader
272   ATTACH my_fragment
273 
274   BIND BUFFER my_fb AS color LOCATION 0
275   BIND BUFFER depth_1 AS depth_stencil
276   FRAMEBUFFER_SIZE 90 180
277 END
278 PIPELINE graphics second_pipeline
279   ATTACH my_shader
280   ATTACH my_fragment
281 
282   BIND BUFFER second_fb AS color LOCATION 9
283   BIND BUFFER depth_2 AS depth_stencil
284   FRAMEBUFFER_SIZE 256 300
285 END)";
286 
287   Parser parser;
288   Result r = parser.Parse(in);
289   ASSERT_TRUE(r.IsSuccess()) << r.Error();
290 
291   auto script = parser.GetScript();
292   const auto& pipelines = script->GetPipelines();
293   ASSERT_EQ(2U, pipelines.size());
294 
295   const auto* pipeline = pipelines[0].get();
296   const auto& color_buffers1 = pipeline->GetColorAttachments();
297   ASSERT_EQ(1U, color_buffers1.size());
298 
299   const auto& buf1 = color_buffers1[0];
300   ASSERT_TRUE(buf1.buffer != nullptr);
301   EXPECT_EQ(0u, buf1.location);
302   EXPECT_EQ(90u * 180u, buf1.buffer->ElementCount());
303   EXPECT_EQ(90u * 180u * 4u, buf1.buffer->ValueCount());
304   EXPECT_EQ(90u * 180u * 4u * sizeof(float), buf1.buffer->GetSizeInBytes());
305 
306   pipeline = pipelines[1].get();
307   const auto& color_buffers2 = pipeline->GetColorAttachments();
308   const auto& buf2 = color_buffers2[0];
309   ASSERT_TRUE(buf2.buffer != nullptr);
310   EXPECT_EQ(9u, buf2.location);
311   EXPECT_EQ(256u * 300u, buf2.buffer->ElementCount());
312   EXPECT_EQ(256u * 300u * 4u, buf2.buffer->ValueCount());
313   EXPECT_EQ(256u * 300u * 4u * sizeof(uint8_t), buf2.buffer->GetSizeInBytes());
314 }
315 
TEST_F(AmberScriptParserTest,BindColorFBSizeSetBeforeBuffer)316 TEST_F(AmberScriptParserTest, BindColorFBSizeSetBeforeBuffer) {
317   std::string in = R"(
318 SHADER vertex my_shader PASSTHROUGH
319 SHADER fragment my_fragment GLSL
320 # GLSL Shader
321 END
322 BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
323 
324 PIPELINE graphics my_pipeline
325   ATTACH my_shader
326   ATTACH my_fragment
327 
328   FRAMEBUFFER_SIZE 90 180
329   BIND BUFFER my_fb AS color LOCATION 0
330 END)";
331 
332   Parser parser;
333   Result r = parser.Parse(in);
334   ASSERT_TRUE(r.IsSuccess()) << r.Error();
335 
336   auto script = parser.GetScript();
337   const auto& pipelines = script->GetPipelines();
338   ASSERT_EQ(1U, pipelines.size());
339 
340   const auto* pipeline = pipelines[0].get();
341   const auto& color_buffers1 = pipeline->GetColorAttachments();
342   ASSERT_EQ(1U, color_buffers1.size());
343 
344   const auto& buf1 = color_buffers1[0];
345   ASSERT_TRUE(buf1.buffer != nullptr);
346   EXPECT_EQ(0u, buf1.location);
347   EXPECT_EQ(90u * 180u, buf1.buffer->ElementCount());
348   EXPECT_EQ(90u * 180u * 4u, buf1.buffer->ValueCount());
349   EXPECT_EQ(90u * 180u * 4u * sizeof(float), buf1.buffer->GetSizeInBytes());
350 }
351 
TEST_F(AmberScriptParserTest,BindColorFBSizeSetAfterBuffer)352 TEST_F(AmberScriptParserTest, BindColorFBSizeSetAfterBuffer) {
353   std::string in = R"(
354 SHADER vertex my_shader PASSTHROUGH
355 SHADER fragment my_fragment GLSL
356 # GLSL Shader
357 END
358 BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
359 
360 PIPELINE graphics my_pipeline
361   ATTACH my_shader
362   ATTACH my_fragment
363 
364   BIND BUFFER my_fb AS color LOCATION 0
365   FRAMEBUFFER_SIZE 90 180
366 END)";
367 
368   Parser parser;
369   Result r = parser.Parse(in);
370   ASSERT_TRUE(r.IsSuccess()) << r.Error();
371 
372   auto script = parser.GetScript();
373   const auto& pipelines = script->GetPipelines();
374   ASSERT_EQ(1U, pipelines.size());
375 
376   const auto* pipeline = pipelines[0].get();
377   const auto& color_buffers1 = pipeline->GetColorAttachments();
378   ASSERT_EQ(1U, color_buffers1.size());
379 
380   const auto& buf1 = color_buffers1[0];
381   ASSERT_TRUE(buf1.buffer != nullptr);
382   EXPECT_EQ(0u, buf1.location);
383   EXPECT_EQ(90u * 180u, buf1.buffer->ElementCount());
384   EXPECT_EQ(90u * 180u * 4u, buf1.buffer->ValueCount());
385   EXPECT_EQ(90u * 180u * 4u * sizeof(float), buf1.buffer->GetSizeInBytes());
386 }
387 
TEST_F(AmberScriptParserTest,BindColorBaseMipLevel)388 TEST_F(AmberScriptParserTest, BindColorBaseMipLevel) {
389   std::string in = R"(
390 SHADER vertex my_shader PASSTHROUGH
391 SHADER fragment my_fragment GLSL
392 # GLSL Shader
393 END
394 BUFFER my_fb FORMAT R32G32B32A32_SFLOAT MIP_LEVELS 2
395 
396 PIPELINE graphics my_pipeline
397   ATTACH my_shader
398   ATTACH my_fragment
399 
400   BIND BUFFER my_fb AS color LOCATION 0 BASE_MIP_LEVEL 1
401   FRAMEBUFFER_SIZE 90 180
402 END)";
403 
404   Parser parser;
405   Result r = parser.Parse(in);
406   ASSERT_TRUE(r.IsSuccess()) << r.Error();
407 
408   auto script = parser.GetScript();
409   const auto& pipelines = script->GetPipelines();
410   ASSERT_EQ(1U, pipelines.size());
411 
412   const auto* pipeline = pipelines[0].get();
413   const auto& color_buffers1 = pipeline->GetColorAttachments();
414   ASSERT_EQ(1U, color_buffers1.size());
415 
416   const auto& buf1 = color_buffers1[0];
417   ASSERT_TRUE(buf1.buffer != nullptr);
418   EXPECT_EQ(1u, buf1.base_mip_level);
419 }
420 
TEST_F(AmberScriptParserTest,BindColorMissingBaseMipLevel)421 TEST_F(AmberScriptParserTest, BindColorMissingBaseMipLevel) {
422   std::string in = R"(
423 SHADER vertex my_shader PASSTHROUGH
424 SHADER fragment my_fragment GLSL
425 # GLSL Shader
426 END
427 BUFFER my_fb FORMAT R32G32B32A32_SFLOAT MIP_LEVELS 2
428 
429 PIPELINE graphics my_pipeline
430   ATTACH my_shader
431   ATTACH my_fragment
432 
433   BIND BUFFER my_fb AS color LOCATION 0 BASE_MIP_LEVEL
434   FRAMEBUFFER_SIZE 90 180
435 END)";
436 
437   Parser parser;
438   Result r = parser.Parse(in);
439   ASSERT_FALSE(r.IsSuccess());
440   EXPECT_EQ("13: invalid value for BASE_MIP_LEVEL", r.Error());
441 }
442 
TEST_F(AmberScriptParserTest,BindColorBaseMipLevelTooLarge)443 TEST_F(AmberScriptParserTest, BindColorBaseMipLevelTooLarge) {
444   std::string in = R"(
445 SHADER vertex my_shader PASSTHROUGH
446 SHADER fragment my_fragment GLSL
447 # GLSL Shader
448 END
449 BUFFER my_fb FORMAT R32G32B32A32_SFLOAT MIP_LEVELS 2
450 
451 PIPELINE graphics my_pipeline
452   ATTACH my_shader
453   ATTACH my_fragment
454 
455   BIND BUFFER my_fb AS color LOCATION 0 BASE_MIP_LEVEL 2
456   FRAMEBUFFER_SIZE 90 180
457 END)";
458 
459   Parser parser;
460   Result r = parser.Parse(in);
461   ASSERT_FALSE(r.IsSuccess());
462   EXPECT_EQ(
463       "12: base mip level (now 2) needs to be larger than the number of buffer "
464       "mip maps (2)",
465       r.Error());
466 }
467 
TEST_F(AmberScriptParserTest,BindColorTooManyMipLevels)468 TEST_F(AmberScriptParserTest, BindColorTooManyMipLevels) {
469   std::string in = R"(
470 SHADER vertex my_shader PASSTHROUGH
471 SHADER fragment my_fragment GLSL
472 # GLSL Shader
473 END
474 BUFFER my_fb FORMAT R32G32B32A32_SFLOAT MIP_LEVELS 20
475 
476 PIPELINE graphics my_pipeline
477   ATTACH my_shader
478   ATTACH my_fragment
479 
480   BIND BUFFER my_fb AS color LOCATION 0
481   FRAMEBUFFER_SIZE 90 180
482 END)";
483 
484   Parser parser;
485   Result r = parser.Parse(in);
486   ASSERT_FALSE(r.IsSuccess());
487   EXPECT_EQ(
488       "color attachment with 20 mip levels would have zero width for level 7",
489       r.Error());
490 }
491 
TEST_F(AmberScriptParserTest,BindDepthBuffer)492 TEST_F(AmberScriptParserTest, BindDepthBuffer) {
493   std::string in = R"(
494 SHADER vertex my_shader PASSTHROUGH
495 SHADER fragment my_fragment GLSL
496 # GLSL Shader
497 END
498 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
499 
500 PIPELINE graphics my_pipeline
501   ATTACH my_shader
502   ATTACH my_fragment
503 
504   BIND BUFFER my_buf AS depth_stencil
505   FRAMEBUFFER_SIZE 90 180
506 END)";
507 
508   Parser parser;
509   Result r = parser.Parse(in);
510   ASSERT_TRUE(r.IsSuccess()) << r.Error();
511 
512   auto script = parser.GetScript();
513   const auto& pipelines = script->GetPipelines();
514   ASSERT_EQ(1U, pipelines.size());
515 
516   const auto* pipeline = pipelines[0].get();
517   const auto& buf = pipeline->GetDepthStencilBuffer();
518   ASSERT_TRUE(buf.buffer != nullptr);
519   EXPECT_EQ(90u * 180u, buf.buffer->ElementCount());
520   EXPECT_EQ(90u * 180u * 4u, buf.buffer->ValueCount());
521   EXPECT_EQ(90u * 180u * 4u * sizeof(float), buf.buffer->GetSizeInBytes());
522 }
523 
TEST_F(AmberScriptParserTest,BindDepthBufferExtraParams)524 TEST_F(AmberScriptParserTest, BindDepthBufferExtraParams) {
525   std::string in = R"(
526 SHADER vertex my_shader PASSTHROUGH
527 SHADER fragment my_fragment GLSL
528 # GLSL Shader
529 END
530 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
531 
532 PIPELINE graphics my_pipeline
533   ATTACH my_shader
534   ATTACH my_fragment
535 
536   BIND BUFFER my_buf AS depth_stencil EXTRA
537   FRAMEBUFFER_SIZE 90 180
538 END)";
539 
540   Parser parser;
541   Result r = parser.Parse(in);
542   ASSERT_FALSE(r.IsSuccess());
543   EXPECT_EQ("12: extra parameters after BIND command: EXTRA", r.Error());
544 }
545 
TEST_F(AmberScriptParserTest,BindBufferMissingBufferName)546 TEST_F(AmberScriptParserTest, BindBufferMissingBufferName) {
547   std::string in = R"(
548 SHADER vertex my_shader PASSTHROUGH
549 SHADER fragment my_fragment GLSL
550 # GLSL Shader
551 END
552 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
553 
554 PIPELINE graphics my_pipeline
555   ATTACH my_shader
556   ATTACH my_fragment
557 
558   BIND BUFFER AS depth_stencil
559   FRAMEBUFFER_SIZE 90 180
560 END)";
561 
562   Parser parser;
563   Result r = parser.Parse(in);
564   ASSERT_FALSE(r.IsSuccess());
565   EXPECT_EQ("12: unknown buffer: AS", r.Error());
566 }
567 
TEST_F(AmberScriptParserTest,BindBufferAsMissingType)568 TEST_F(AmberScriptParserTest, BindBufferAsMissingType) {
569   std::string in = R"(
570 SHADER vertex my_shader PASSTHROUGH
571 SHADER fragment my_fragment GLSL
572 # GLSL Shader
573 END
574 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
575 
576 PIPELINE graphics my_pipeline
577   ATTACH my_shader
578   ATTACH my_fragment
579 
580   BIND BUFFER my_buf AS
581   FRAMEBUFFER_SIZE 90 180
582 END)";
583 
584   Parser parser;
585   Result r = parser.Parse(in);
586   ASSERT_FALSE(r.IsSuccess());
587   EXPECT_EQ("13: invalid token for BUFFER type", r.Error());
588 }
589 
TEST_F(AmberScriptParserTest,BindBufferAsInvalidType)590 TEST_F(AmberScriptParserTest, BindBufferAsInvalidType) {
591   std::string in = R"(
592 SHADER vertex my_shader PASSTHROUGH
593 SHADER fragment my_fragment GLSL
594 # GLSL Shader
595 END
596 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
597 
598 PIPELINE graphics my_pipeline
599   ATTACH my_shader
600   ATTACH my_fragment
601 
602   BIND BUFFER my_buf AS
603   FRAMEBUFFER_SIZE 90 180
604 END)";
605 
606   Parser parser;
607   Result r = parser.Parse(in);
608   ASSERT_FALSE(r.IsSuccess());
609   EXPECT_EQ("13: invalid token for BUFFER type", r.Error());
610 }
611 
TEST_F(AmberScriptParserTest,BindDepthBufferUnknownBuffer)612 TEST_F(AmberScriptParserTest, BindDepthBufferUnknownBuffer) {
613   std::string in = R"(
614 SHADER vertex my_shader PASSTHROUGH
615 SHADER fragment my_fragment GLSL
616 # GLSL Shader
617 END
618 
619 PIPELINE graphics my_pipeline
620   ATTACH my_shader
621   ATTACH my_fragment
622 
623   BIND BUFFER my_buf AS depth_stencil
624   FRAMEBUFFER_SIZE 90 180
625 END)";
626 
627   Parser parser;
628   Result r = parser.Parse(in);
629   ASSERT_FALSE(r.IsSuccess());
630   EXPECT_EQ("11: unknown buffer: my_buf", r.Error());
631 }
632 
TEST_F(AmberScriptParserTest,BindBufferMultipleDepthBuffers)633 TEST_F(AmberScriptParserTest, BindBufferMultipleDepthBuffers) {
634   std::string in = R"(
635 SHADER vertex my_shader PASSTHROUGH
636 SHADER fragment my_fragment GLSL
637 # GLSL Shader
638 END
639 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
640 BUFFER my_buf2 FORMAT R32G32B32A32_SFLOAT
641 
642 PIPELINE graphics my_pipeline
643   ATTACH my_shader
644   ATTACH my_fragment
645 
646   BIND BUFFER my_buf AS depth_stencil
647   BIND BUFFER my_buf AS depth_stencil
648 END)";
649 
650   Parser parser;
651   Result r = parser.Parse(in);
652   ASSERT_FALSE(r.IsSuccess());
653   EXPECT_EQ("14: can only bind one depth/stencil buffer in a PIPELINE",
654             r.Error());
655 }
656 
TEST_F(AmberScriptParserTest,BindVertexData)657 TEST_F(AmberScriptParserTest, BindVertexData) {
658   std::string in = R"(
659 SHADER vertex my_shader PASSTHROUGH
660 SHADER fragment my_fragment GLSL
661 # GLSL Shader
662 END
663 BUFFER my_buf DATA_TYPE int8 SIZE 5 FILL 5
664 BUFFER my_buf2 DATA_TYPE int8 SIZE 5 FILL 5
665 
666 PIPELINE graphics my_pipeline
667   ATTACH my_shader
668   ATTACH my_fragment
669 
670   VERTEX_DATA my_buf LOCATION 0
671   VERTEX_DATA my_buf2 LOCATION 1
672 END)";
673 
674   Parser parser;
675   Result r = parser.Parse(in);
676   ASSERT_TRUE(r.IsSuccess()) << r.Error();
677 
678   auto script = parser.GetScript();
679   const auto& pipelines = script->GetPipelines();
680   ASSERT_EQ(1U, pipelines.size());
681 
682   const auto* pipeline = pipelines[0].get();
683   const auto& vertex_buffers = pipeline->GetVertexBuffers();
684   ASSERT_EQ(2u, vertex_buffers.size());
685 
686   const auto& info1 = vertex_buffers[0];
687   ASSERT_TRUE(info1.buffer != nullptr);
688   EXPECT_EQ(0u, info1.location);
689   EXPECT_EQ(InputRate::kVertex, info1.input_rate);
690 
691   const auto& info2 = vertex_buffers[1];
692   ASSERT_TRUE(info2.buffer != nullptr);
693   EXPECT_EQ(1u, info2.location);
694   EXPECT_EQ(InputRate::kVertex, info2.input_rate);
695 }
696 
TEST_F(AmberScriptParserTest,BindVertexDataDuplicateLocation)697 TEST_F(AmberScriptParserTest, BindVertexDataDuplicateLocation) {
698   std::string in = R"(
699 SHADER vertex my_shader PASSTHROUGH
700 SHADER fragment my_fragment GLSL
701 # GLSL Shader
702 END
703 BUFFER my_buf DATA_TYPE int8 SIZE 50 FILL 5
704 BUFFER my_buf2 DATA_TYPE int8 SIZE 50 FILL 5
705 
706 PIPELINE graphics my_pipeline
707   ATTACH my_shader
708   ATTACH my_fragment
709 
710   VERTEX_DATA my_buf LOCATION 0
711   VERTEX_DATA my_buf2 LOCATION 0
712 END)";
713 
714   Parser parser;
715   Result r = parser.Parse(in);
716   ASSERT_FALSE(r.IsSuccess());
717   EXPECT_EQ("14: can not bind two vertex buffers to the same LOCATION",
718             r.Error());
719 }
720 
TEST_F(AmberScriptParserTest,BindVertexDataDuplicateBinding)721 TEST_F(AmberScriptParserTest, BindVertexDataDuplicateBinding) {
722   std::string in = R"(
723 SHADER vertex my_shader PASSTHROUGH
724 SHADER fragment my_fragment GLSL
725 # GLSL Shader
726 END
727 BUFFER my_buf DATA_TYPE int8 SIZE 50 FILL 5
728 
729 PIPELINE graphics my_pipeline
730   ATTACH my_shader
731   ATTACH my_fragment
732 
733   VERTEX_DATA my_buf LOCATION 0
734   VERTEX_DATA my_buf LOCATION 1 OFFSET 10
735 END)";
736 
737   Parser parser;
738   Result r = parser.Parse(in);
739   ASSERT_TRUE(r.IsSuccess());
740 
741   auto script = parser.GetScript();
742   const auto& pipelines = script->GetPipelines();
743   ASSERT_EQ(1U, pipelines.size());
744 
745   const auto* pipeline = pipelines[0].get();
746   const auto& vertex_buffers = pipeline->GetVertexBuffers();
747   ASSERT_EQ(2u, vertex_buffers.size());
748 
749   const auto& info1 = vertex_buffers[0];
750   ASSERT_TRUE(info1.buffer != nullptr);
751   EXPECT_EQ(0u, info1.location);
752   EXPECT_EQ(0u, info1.offset);
753 
754   const auto& info2 = vertex_buffers[1];
755   ASSERT_TRUE(info2.buffer != nullptr);
756   EXPECT_EQ(1u, info2.location);
757   EXPECT_EQ(10u, info2.offset);
758 }
759 
TEST_F(AmberScriptParserTest,BindVertexDataMissingBuffer)760 TEST_F(AmberScriptParserTest, BindVertexDataMissingBuffer) {
761   std::string in = R"(
762 SHADER vertex my_shader PASSTHROUGH
763 SHADER fragment my_fragment GLSL
764 # GLSL Shader
765 END
766 BUFFER my_buf DATA_TYPE int8 SIZE 50 FILL 5
767 
768 PIPELINE graphics my_pipeline
769   ATTACH my_shader
770   ATTACH my_fragment
771 
772   VERTEX_DATA LOCATION 0
773 END)";
774 
775   Parser parser;
776   Result r = parser.Parse(in);
777   ASSERT_FALSE(r.IsSuccess());
778   EXPECT_EQ("12: unknown buffer: LOCATION", r.Error());
779 }
780 
TEST_F(AmberScriptParserTest,BindVertexDataUnknownBuffer)781 TEST_F(AmberScriptParserTest, BindVertexDataUnknownBuffer) {
782   std::string in = R"(
783 SHADER vertex my_shader PASSTHROUGH
784 SHADER fragment my_fragment GLSL
785 # GLSL Shader
786 END
787 
788 PIPELINE graphics my_pipeline
789   ATTACH my_shader
790   ATTACH my_fragment
791 
792   VERTEX_DATA my_buf LOCATION 0
793 END)";
794 
795   Parser parser;
796   Result r = parser.Parse(in);
797   ASSERT_FALSE(r.IsSuccess());
798   EXPECT_EQ("11: unknown buffer: my_buf", r.Error());
799 }
800 
TEST_F(AmberScriptParserTest,BindVertexDataMissingLocation)801 TEST_F(AmberScriptParserTest, BindVertexDataMissingLocation) {
802   std::string in = R"(
803 SHADER vertex my_shader PASSTHROUGH
804 SHADER fragment my_fragment GLSL
805 # GLSL Shader
806 END
807 BUFFER my_buf DATA_TYPE int8 SIZE 50 FILL 5
808 
809 PIPELINE graphics my_pipeline
810   ATTACH my_shader
811   ATTACH my_fragment
812 
813   VERTEX_DATA my_buf
814 END)";
815 
816   Parser parser;
817   Result r = parser.Parse(in);
818   ASSERT_FALSE(r.IsSuccess());
819   EXPECT_EQ("13: VERTEX_DATA missing LOCATION", r.Error());
820 }
821 
TEST_F(AmberScriptParserTest,BindVertexDataMissingLocationValue)822 TEST_F(AmberScriptParserTest, BindVertexDataMissingLocationValue) {
823   std::string in = R"(
824 SHADER vertex my_shader PASSTHROUGH
825 SHADER fragment my_fragment GLSL
826 # GLSL Shader
827 END
828 BUFFER my_buf DATA_TYPE int8 SIZE 50 FILL 5
829 
830 PIPELINE graphics my_pipeline
831   ATTACH my_shader
832   ATTACH my_fragment
833 
834   VERTEX_DATA my_buf LOCATION
835 END)";
836 
837   Parser parser;
838   Result r = parser.Parse(in);
839   ASSERT_FALSE(r.IsSuccess());
840   EXPECT_EQ("13: invalid value for VERTEX_DATA LOCATION", r.Error());
841 }
842 
TEST_F(AmberScriptParserTest,BindVertexDataExtraParameters)843 TEST_F(AmberScriptParserTest, BindVertexDataExtraParameters) {
844   std::string in = R"(
845 SHADER vertex my_shader PASSTHROUGH
846 SHADER fragment my_fragment GLSL
847 # GLSL Shader
848 END
849 BUFFER my_buf DATA_TYPE int8 SIZE 50 FILL 5
850 
851 PIPELINE graphics my_pipeline
852   ATTACH my_shader
853   ATTACH my_fragment
854 
855   VERTEX_DATA my_buf LOCATION 0 EXTRA
856 END)";
857 
858   Parser parser;
859   Result r = parser.Parse(in);
860   ASSERT_FALSE(r.IsSuccess());
861   EXPECT_EQ("12: unexpected identifier for VERTEX_DATA command: EXTRA",
862             r.Error());
863 }
864 
TEST_F(AmberScriptParserTest,BindVertexDataInputRate)865 TEST_F(AmberScriptParserTest, BindVertexDataInputRate) {
866   std::string in = R"(
867 SHADER vertex my_shader PASSTHROUGH
868 SHADER fragment my_fragment GLSL
869 # GLSL Shader
870 END
871 BUFFER my_buf DATA_TYPE int8 SIZE 5 FILL 5
872 BUFFER my_buf2 DATA_TYPE int8 SIZE 5 FILL 5
873 
874 PIPELINE graphics my_pipeline
875   ATTACH my_shader
876   ATTACH my_fragment
877 
878   VERTEX_DATA my_buf LOCATION 0 RATE vertex
879   VERTEX_DATA my_buf2 LOCATION 1 RATE instance
880 END)";
881 
882   Parser parser;
883   Result r = parser.Parse(in);
884   ASSERT_TRUE(r.IsSuccess()) << r.Error();
885 
886   auto script = parser.GetScript();
887   const auto& pipelines = script->GetPipelines();
888   ASSERT_EQ(1U, pipelines.size());
889 
890   const auto* pipeline = pipelines[0].get();
891   const auto& vertex_buffers = pipeline->GetVertexBuffers();
892   ASSERT_EQ(2u, vertex_buffers.size());
893 
894   const auto& info1 = vertex_buffers[0];
895   ASSERT_TRUE(info1.buffer != nullptr);
896   EXPECT_EQ(0u, info1.location);
897   EXPECT_EQ(InputRate::kVertex, info1.input_rate);
898 
899   const auto& info2 = vertex_buffers[1];
900   ASSERT_TRUE(info2.buffer != nullptr);
901   EXPECT_EQ(1u, info2.location);
902   EXPECT_EQ(InputRate::kInstance, info2.input_rate);
903 }
904 
TEST_F(AmberScriptParserTest,BindVertexDataInputRateMissingValue)905 TEST_F(AmberScriptParserTest, BindVertexDataInputRateMissingValue) {
906   std::string in = R"(
907 SHADER vertex my_shader PASSTHROUGH
908 SHADER fragment my_fragment GLSL
909 # GLSL Shader
910 END
911 BUFFER my_buf DATA_TYPE int8 SIZE 5 FILL 5
912 
913 PIPELINE graphics my_pipeline
914   ATTACH my_shader
915   ATTACH my_fragment
916 
917   VERTEX_DATA my_buf LOCATION 0 RATE
918 END)";
919 
920   Parser parser;
921   Result r = parser.Parse(in);
922   ASSERT_FALSE(r.IsSuccess());
923   EXPECT_EQ("13: missing input rate value for RATE", r.Error());
924 }
925 
TEST_F(AmberScriptParserTest,BindVertexDataInputRateInvalidValue)926 TEST_F(AmberScriptParserTest, BindVertexDataInputRateInvalidValue) {
927   std::string in = R"(
928 SHADER vertex my_shader PASSTHROUGH
929 SHADER fragment my_fragment GLSL
930 # GLSL Shader
931 END
932 BUFFER my_buf DATA_TYPE int8 SIZE 5 FILL 5
933 
934 PIPELINE graphics my_pipeline
935   ATTACH my_shader
936   ATTACH my_fragment
937 
938   VERTEX_DATA my_buf LOCATION 0 RATE foo
939 END)";
940 
941   Parser parser;
942   Result r = parser.Parse(in);
943   ASSERT_FALSE(r.IsSuccess());
944   EXPECT_EQ("12: expecting 'vertex' or 'instance' for RATE value", r.Error());
945 }
946 
TEST_F(AmberScriptParserTest,BindVertexDataOffset)947 TEST_F(AmberScriptParserTest, BindVertexDataOffset) {
948   std::string in = R"(
949 SHADER vertex my_shader PASSTHROUGH
950 SHADER fragment my_fragment GLSL
951 # GLSL Shader
952 END
953 BUFFER my_buf DATA_TYPE int8 SIZE 5 FILL 5
954 BUFFER my_buf2 DATA_TYPE int8 SIZE 5 FILL 5
955 
956 PIPELINE graphics my_pipeline
957   ATTACH my_shader
958   ATTACH my_fragment
959 
960   VERTEX_DATA my_buf LOCATION 0 OFFSET 5
961   VERTEX_DATA my_buf2 LOCATION 1 OFFSET 10
962 END)";
963 
964   Parser parser;
965   Result r = parser.Parse(in);
966   ASSERT_TRUE(r.IsSuccess()) << r.Error();
967 
968   auto script = parser.GetScript();
969   const auto& pipelines = script->GetPipelines();
970   ASSERT_EQ(1U, pipelines.size());
971 
972   const auto* pipeline = pipelines[0].get();
973   const auto& vertex_buffers = pipeline->GetVertexBuffers();
974   ASSERT_EQ(2u, vertex_buffers.size());
975 
976   const auto& info1 = vertex_buffers[0];
977   ASSERT_TRUE(info1.buffer != nullptr);
978   EXPECT_EQ(0u, info1.location);
979   EXPECT_EQ(5u, info1.offset);
980 
981   const auto& info2 = vertex_buffers[1];
982   ASSERT_TRUE(info2.buffer != nullptr);
983   EXPECT_EQ(1u, info2.location);
984   EXPECT_EQ(10u, info2.offset);
985 }
986 
TEST_F(AmberScriptParserTest,BindVertexDataOffsetMissingValue)987 TEST_F(AmberScriptParserTest, BindVertexDataOffsetMissingValue) {
988   std::string in = R"(
989 SHADER vertex my_shader PASSTHROUGH
990 SHADER fragment my_fragment GLSL
991 # GLSL Shader
992 END
993 BUFFER my_buf DATA_TYPE int8 SIZE 5 FILL 5
994 
995 PIPELINE graphics my_pipeline
996   ATTACH my_shader
997   ATTACH my_fragment
998 
999   VERTEX_DATA my_buf LOCATION 0 OFFSET
1000 END)";
1001 
1002   Parser parser;
1003   Result r = parser.Parse(in);
1004   ASSERT_FALSE(r.IsSuccess());
1005   EXPECT_EQ("13: expected unsigned integer for OFFSET", r.Error());
1006 }
1007 
TEST_F(AmberScriptParserTest,BindVertexDataOffsetIncorrectValue)1008 TEST_F(AmberScriptParserTest, BindVertexDataOffsetIncorrectValue) {
1009   std::string in = R"(
1010 SHADER vertex my_shader PASSTHROUGH
1011 SHADER fragment my_fragment GLSL
1012 # GLSL Shader
1013 END
1014 BUFFER my_buf DATA_TYPE int8 SIZE 5 FILL 5
1015 
1016 PIPELINE graphics my_pipeline
1017   ATTACH my_shader
1018   ATTACH my_fragment
1019 
1020   VERTEX_DATA my_buf LOCATION 0 OFFSET foo
1021 END)";
1022 
1023   Parser parser;
1024   Result r = parser.Parse(in);
1025   ASSERT_FALSE(r.IsSuccess());
1026   EXPECT_EQ("12: expected unsigned integer for OFFSET", r.Error());
1027 }
1028 
TEST_F(AmberScriptParserTest,BindVertexDataStride)1029 TEST_F(AmberScriptParserTest, BindVertexDataStride) {
1030   std::string in = R"(
1031 SHADER vertex my_shader PASSTHROUGH
1032 SHADER fragment my_fragment GLSL
1033 # GLSL Shader
1034 END
1035 BUFFER my_buf DATA_TYPE int8 SIZE 5 FILL 5
1036 BUFFER my_buf2 DATA_TYPE int8 SIZE 5 FILL 5
1037 
1038 PIPELINE graphics my_pipeline
1039   ATTACH my_shader
1040   ATTACH my_fragment
1041 
1042   VERTEX_DATA my_buf LOCATION 0 STRIDE 5
1043   VERTEX_DATA my_buf2 LOCATION 1 STRIDE 10
1044 END)";
1045 
1046   Parser parser;
1047   Result r = parser.Parse(in);
1048   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1049 
1050   auto script = parser.GetScript();
1051   const auto& pipelines = script->GetPipelines();
1052   ASSERT_EQ(1U, pipelines.size());
1053 
1054   const auto* pipeline = pipelines[0].get();
1055   const auto& vertex_buffers = pipeline->GetVertexBuffers();
1056   ASSERT_EQ(2u, vertex_buffers.size());
1057 
1058   const auto& info1 = vertex_buffers[0];
1059   ASSERT_TRUE(info1.buffer != nullptr);
1060   EXPECT_EQ(0u, info1.location);
1061   EXPECT_EQ(5u, info1.stride);
1062 
1063   const auto& info2 = vertex_buffers[1];
1064   ASSERT_TRUE(info2.buffer != nullptr);
1065   EXPECT_EQ(1u, info2.location);
1066   EXPECT_EQ(10u, info2.stride);
1067 }
1068 
TEST_F(AmberScriptParserTest,BindVertexDataStrideFromFormat)1069 TEST_F(AmberScriptParserTest, BindVertexDataStrideFromFormat) {
1070   std::string in = R"(
1071 SHADER vertex my_shader PASSTHROUGH
1072 SHADER fragment my_fragment GLSL
1073 # GLSL Shader
1074 END
1075 BUFFER my_buf DATA_TYPE int8 SIZE 5 FILL 5
1076 BUFFER my_buf2 DATA_TYPE int8 SIZE 5 FILL 5
1077 
1078 PIPELINE graphics my_pipeline
1079   ATTACH my_shader
1080   ATTACH my_fragment
1081 
1082   VERTEX_DATA my_buf LOCATION 0
1083   VERTEX_DATA my_buf2 LOCATION 1 FORMAT R16_UINT
1084 END)";
1085 
1086   Parser parser;
1087   Result r = parser.Parse(in);
1088   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1089 
1090   auto script = parser.GetScript();
1091   const auto& pipelines = script->GetPipelines();
1092   ASSERT_EQ(1U, pipelines.size());
1093 
1094   const auto* pipeline = pipelines[0].get();
1095   const auto& vertex_buffers = pipeline->GetVertexBuffers();
1096   ASSERT_EQ(2u, vertex_buffers.size());
1097 
1098   const auto& info1 = vertex_buffers[0];
1099   ASSERT_TRUE(info1.buffer != nullptr);
1100   EXPECT_EQ(0u, info1.location);
1101   EXPECT_EQ(1u, info1.stride);
1102 
1103   const auto& info2 = vertex_buffers[1];
1104   ASSERT_TRUE(info2.buffer != nullptr);
1105   EXPECT_EQ(1u, info2.location);
1106   EXPECT_EQ(2u, info2.stride);
1107 }
1108 
TEST_F(AmberScriptParserTest,BindVertexDataStrideMissingValue)1109 TEST_F(AmberScriptParserTest, BindVertexDataStrideMissingValue) {
1110   std::string in = R"(
1111 SHADER vertex my_shader PASSTHROUGH
1112 SHADER fragment my_fragment GLSL
1113 # GLSL Shader
1114 END
1115 BUFFER my_buf DATA_TYPE int8 SIZE 5 FILL 5
1116 
1117 PIPELINE graphics my_pipeline
1118   ATTACH my_shader
1119   ATTACH my_fragment
1120 
1121   VERTEX_DATA my_buf LOCATION 0 STRIDE
1122 END)";
1123 
1124   Parser parser;
1125   Result r = parser.Parse(in);
1126   ASSERT_FALSE(r.IsSuccess());
1127   EXPECT_EQ("13: expected unsigned integer for STRIDE", r.Error());
1128 }
1129 
TEST_F(AmberScriptParserTest,BindVertexDataStrideIncorrectValue)1130 TEST_F(AmberScriptParserTest, BindVertexDataStrideIncorrectValue) {
1131   std::string in = R"(
1132 SHADER vertex my_shader PASSTHROUGH
1133 SHADER fragment my_fragment GLSL
1134 # GLSL Shader
1135 END
1136 BUFFER my_buf DATA_TYPE int8 SIZE 5 FILL 5
1137 
1138 PIPELINE graphics my_pipeline
1139   ATTACH my_shader
1140   ATTACH my_fragment
1141 
1142   VERTEX_DATA my_buf LOCATION 0 STRIDE foo
1143 END)";
1144 
1145   Parser parser;
1146   Result r = parser.Parse(in);
1147   ASSERT_FALSE(r.IsSuccess());
1148   EXPECT_EQ("12: expected unsigned integer for STRIDE", r.Error());
1149 }
1150 
TEST_F(AmberScriptParserTest,BindVertexDataStrideZero)1151 TEST_F(AmberScriptParserTest, BindVertexDataStrideZero) {
1152   std::string in = R"(
1153 SHADER vertex my_shader PASSTHROUGH
1154 SHADER fragment my_fragment GLSL
1155 # GLSL Shader
1156 END
1157 BUFFER my_buf DATA_TYPE int8 SIZE 5 FILL 5
1158 
1159 PIPELINE graphics my_pipeline
1160   ATTACH my_shader
1161   ATTACH my_fragment
1162 
1163   VERTEX_DATA my_buf LOCATION 0 STRIDE 0
1164 END)";
1165 
1166   Parser parser;
1167   Result r = parser.Parse(in);
1168   ASSERT_FALSE(r.IsSuccess());
1169   EXPECT_EQ("12: STRIDE needs to be larger than zero", r.Error());
1170 }
1171 
TEST_F(AmberScriptParserTest,BindVertexDataFormat)1172 TEST_F(AmberScriptParserTest, BindVertexDataFormat) {
1173   std::string in = R"(
1174 SHADER vertex my_shader PASSTHROUGH
1175 SHADER fragment my_fragment GLSL
1176 # GLSL Shader
1177 END
1178 BUFFER my_buf DATA_TYPE int8 SIZE 5 FILL 5
1179 BUFFER my_buf2 DATA_TYPE int8 SIZE 5 FILL 5
1180 
1181 PIPELINE graphics my_pipeline
1182   ATTACH my_shader
1183   ATTACH my_fragment
1184 
1185   VERTEX_DATA my_buf LOCATION 0 FORMAT R8G8_UNORM
1186   VERTEX_DATA my_buf2 LOCATION 1 FORMAT R8_SRGB
1187 END)";
1188 
1189   Parser parser;
1190   Result r = parser.Parse(in);
1191   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1192 
1193   auto script = parser.GetScript();
1194   const auto& pipelines = script->GetPipelines();
1195   ASSERT_EQ(1U, pipelines.size());
1196 
1197   const auto* pipeline = pipelines[0].get();
1198   const auto& vertex_buffers = pipeline->GetVertexBuffers();
1199   ASSERT_EQ(2u, vertex_buffers.size());
1200 
1201   const auto& info1 = vertex_buffers[0];
1202   ASSERT_TRUE(info1.buffer != nullptr);
1203   EXPECT_EQ(0u, info1.location);
1204   EXPECT_EQ(FormatType::kR8G8_UNORM, info1.format->GetFormatType());
1205 
1206   const auto& info2 = vertex_buffers[1];
1207   ASSERT_TRUE(info2.buffer != nullptr);
1208   EXPECT_EQ(1u, info2.location);
1209   EXPECT_EQ(FormatType::kR8_SRGB, info2.format->GetFormatType());
1210 }
1211 
TEST_F(AmberScriptParserTest,BindVertexDataFormatMissingValue)1212 TEST_F(AmberScriptParserTest, BindVertexDataFormatMissingValue) {
1213   std::string in = R"(
1214 SHADER vertex my_shader PASSTHROUGH
1215 SHADER fragment my_fragment GLSL
1216 # GLSL Shader
1217 END
1218 BUFFER my_buf DATA_TYPE int8 SIZE 5 FILL 5
1219 
1220 PIPELINE graphics my_pipeline
1221   ATTACH my_shader
1222   ATTACH my_fragment
1223 
1224   VERTEX_DATA my_buf LOCATION 0 FORMAT
1225 END)";
1226 
1227   Parser parser;
1228   Result r = parser.Parse(in);
1229   ASSERT_FALSE(r.IsSuccess());
1230   EXPECT_EQ("13: vertex data FORMAT must be an identifier", r.Error());
1231 }
1232 
TEST_F(AmberScriptParserTest,BindVertexDataFormatIncorrectValue)1233 TEST_F(AmberScriptParserTest, BindVertexDataFormatIncorrectValue) {
1234   std::string in = R"(
1235 SHADER vertex my_shader PASSTHROUGH
1236 SHADER fragment my_fragment GLSL
1237 # GLSL Shader
1238 END
1239 BUFFER my_buf DATA_TYPE int8 SIZE 5 FILL 5
1240 
1241 PIPELINE graphics my_pipeline
1242   ATTACH my_shader
1243   ATTACH my_fragment
1244 
1245   VERTEX_DATA my_buf LOCATION 0 FORMAT foo
1246 END)";
1247 
1248   Parser parser;
1249   Result r = parser.Parse(in);
1250   ASSERT_FALSE(r.IsSuccess());
1251   EXPECT_EQ("12: invalid vertex data FORMAT", r.Error());
1252 }
1253 
TEST_F(AmberScriptParserTest,BindIndexData)1254 TEST_F(AmberScriptParserTest, BindIndexData) {
1255   std::string in = R"(
1256 SHADER vertex my_shader PASSTHROUGH
1257 SHADER fragment my_fragment GLSL
1258 # GLSL Shader
1259 END
1260 BUFFER my_buf DATA_TYPE int8 SIZE 50 FILL 5
1261 
1262 PIPELINE graphics my_pipeline
1263   ATTACH my_shader
1264   ATTACH my_fragment
1265 
1266   INDEX_DATA my_buf
1267 END)";
1268 
1269   Parser parser;
1270   Result r = parser.Parse(in);
1271   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1272 
1273   auto script = parser.GetScript();
1274   const auto& pipelines = script->GetPipelines();
1275   ASSERT_EQ(1U, pipelines.size());
1276 
1277   const auto* pipeline = pipelines[0].get();
1278   const auto* buf = pipeline->GetIndexBuffer();
1279   ASSERT_TRUE(buf != nullptr);
1280 }
1281 
TEST_F(AmberScriptParserTest,BindIndexataMissingBuffer)1282 TEST_F(AmberScriptParserTest, BindIndexataMissingBuffer) {
1283   std::string in = R"(
1284 SHADER vertex my_shader PASSTHROUGH
1285 SHADER fragment my_fragment GLSL
1286 # GLSL Shader
1287 END
1288 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
1289 
1290 PIPELINE graphics my_pipeline
1291   ATTACH my_shader
1292   ATTACH my_fragment
1293 
1294   INDEX_DATA
1295 END)";
1296 
1297   Parser parser;
1298   Result r = parser.Parse(in);
1299   ASSERT_FALSE(r.IsSuccess());
1300   EXPECT_EQ("13: missing buffer name in INDEX_DATA command", r.Error());
1301 }
1302 
TEST_F(AmberScriptParserTest,BindIndexDataUnknownBuffer)1303 TEST_F(AmberScriptParserTest, BindIndexDataUnknownBuffer) {
1304   std::string in = R"(
1305 SHADER vertex my_shader PASSTHROUGH
1306 SHADER fragment my_fragment GLSL
1307 # GLSL Shader
1308 END
1309 
1310 PIPELINE graphics my_pipeline
1311   ATTACH my_shader
1312   ATTACH my_fragment
1313 
1314   INDEX_DATA my_buf
1315 END)";
1316 
1317   Parser parser;
1318   Result r = parser.Parse(in);
1319   ASSERT_FALSE(r.IsSuccess());
1320   EXPECT_EQ("11: unknown buffer: my_buf", r.Error());
1321 }
1322 
TEST_F(AmberScriptParserTest,BindIndexDataExtraParameters)1323 TEST_F(AmberScriptParserTest, BindIndexDataExtraParameters) {
1324   std::string in = R"(
1325 SHADER vertex my_shader PASSTHROUGH
1326 SHADER fragment my_fragment GLSL
1327 # GLSL Shader
1328 END
1329 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
1330 
1331 PIPELINE graphics my_pipeline
1332   ATTACH my_shader
1333   ATTACH my_fragment
1334 
1335   INDEX_DATA my_buf EXTRA
1336 END)";
1337 
1338   Parser parser;
1339   Result r = parser.Parse(in);
1340   ASSERT_FALSE(r.IsSuccess());
1341   EXPECT_EQ("12: extra parameters after INDEX_DATA command: EXTRA", r.Error());
1342 }
1343 
TEST_F(AmberScriptParserTest,BindIndexDataMultiple)1344 TEST_F(AmberScriptParserTest, BindIndexDataMultiple) {
1345   std::string in = R"(
1346 SHADER vertex my_shader PASSTHROUGH
1347 SHADER fragment my_fragment GLSL
1348 # GLSL Shader
1349 END
1350 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
1351 
1352 PIPELINE graphics my_pipeline
1353   ATTACH my_shader
1354   ATTACH my_fragment
1355 
1356   INDEX_DATA my_buf
1357   INDEX_DATA my_buf
1358 END)";
1359 
1360   Parser parser;
1361   Result r = parser.Parse(in);
1362   ASSERT_FALSE(r.IsSuccess());
1363   EXPECT_EQ("13: can only bind one INDEX_DATA buffer in a pipeline", r.Error());
1364 }
1365 
TEST_F(AmberScriptParserTest,BindBuffer)1366 TEST_F(AmberScriptParserTest, BindBuffer) {
1367   std::string in = R"(
1368 SHADER vertex my_shader PASSTHROUGH
1369 SHADER fragment my_fragment GLSL
1370 # GLSL Shader
1371 END
1372 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
1373 
1374 PIPELINE graphics my_pipeline
1375   ATTACH my_shader
1376   ATTACH my_fragment
1377 
1378   BIND BUFFER my_buf AS uniform DESCRIPTOR_SET 1 BINDING 2
1379 END
1380 )";
1381 
1382   Parser parser;
1383   Result r = parser.Parse(in);
1384   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1385 
1386   auto script = parser.GetScript();
1387   const auto& pipelines = script->GetPipelines();
1388   ASSERT_EQ(1U, pipelines.size());
1389 
1390   const auto* pipeline = pipelines[0].get();
1391   const auto& bufs = pipeline->GetBuffers();
1392   ASSERT_EQ(1U, bufs.size());
1393   EXPECT_EQ(BufferType::kUniform, bufs[0].type);
1394   EXPECT_EQ(1U, bufs[0].descriptor_set);
1395   EXPECT_EQ(2U, bufs[0].binding);
1396   EXPECT_EQ(0U, bufs[0].descriptor_offset);
1397   EXPECT_EQ(~0ULL, bufs[0].descriptor_range);
1398   EXPECT_EQ(static_cast<uint32_t>(0), bufs[0].location);
1399   EXPECT_EQ(FormatType::kR32G32B32A32_SFLOAT,
1400             bufs[0].buffer->GetFormat()->GetFormatType());
1401 }
1402 
TEST_F(AmberScriptParserTest,BindBufferDescriptorOffsetAndRange)1403 TEST_F(AmberScriptParserTest, BindBufferDescriptorOffsetAndRange) {
1404   std::string in = R"(
1405 SHADER vertex my_shader PASSTHROUGH
1406 SHADER fragment my_fragment GLSL
1407 # GLSL Shader
1408 END
1409 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
1410 
1411 PIPELINE graphics my_pipeline
1412   ATTACH my_shader
1413   ATTACH my_fragment
1414 
1415   BIND BUFFER my_buf AS uniform DESCRIPTOR_SET 1 BINDING 2 DESCRIPTOR_OFFSET 256 DESCRIPTOR_RANGE 512
1416   BIND BUFFER my_buf AS uniform DESCRIPTOR_SET 1 BINDING 3 DESCRIPTOR_OFFSET 256 DESCRIPTOR_RANGE -1
1417 END
1418 )";
1419 
1420   Parser parser;
1421   Result r = parser.Parse(in);
1422   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1423 
1424   auto script = parser.GetScript();
1425   const auto& pipelines = script->GetPipelines();
1426   ASSERT_EQ(1U, pipelines.size());
1427 
1428   const auto* pipeline = pipelines[0].get();
1429   const auto& bufs = pipeline->GetBuffers();
1430   ASSERT_EQ(2U, bufs.size());
1431   EXPECT_EQ(BufferType::kUniform, bufs[0].type);
1432   EXPECT_EQ(1U, bufs[0].descriptor_set);
1433   EXPECT_EQ(2U, bufs[0].binding);
1434   EXPECT_EQ(256U, bufs[0].descriptor_offset);
1435   EXPECT_EQ(512U, bufs[0].descriptor_range);
1436   EXPECT_EQ(static_cast<uint32_t>(0), bufs[0].location);
1437   EXPECT_EQ(FormatType::kR32G32B32A32_SFLOAT,
1438             bufs[0].buffer->GetFormat()->GetFormatType());
1439   // Verify the descriptor range from the second buffer.
1440   EXPECT_EQ(~0ULL, bufs[1].descriptor_range);
1441 }
1442 
TEST_F(AmberScriptParserTest,BindBufferMissingBindingValue)1443 TEST_F(AmberScriptParserTest, BindBufferMissingBindingValue) {
1444   std::string in = R"(
1445 SHADER vertex my_shader PASSTHROUGH
1446 SHADER fragment my_fragment GLSL
1447 # GLSL Shader
1448 END
1449 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
1450 
1451 PIPELINE graphics my_pipeline
1452   ATTACH my_shader
1453   ATTACH my_fragment
1454 
1455   BIND BUFFER my_buf AS uniform DESCRIPTOR_SET 1 BINDING
1456 END)";
1457 
1458   Parser parser;
1459   Result r = parser.Parse(in);
1460   ASSERT_FALSE(r.IsSuccess());
1461   EXPECT_EQ("13: invalid value for BINDING in BIND command", r.Error());
1462 }
1463 
TEST_F(AmberScriptParserTest,BindBufferMissingBinding)1464 TEST_F(AmberScriptParserTest, BindBufferMissingBinding) {
1465   std::string in = R"(
1466 SHADER vertex my_shader PASSTHROUGH
1467 SHADER fragment my_fragment GLSL
1468 # GLSL Shader
1469 END
1470 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
1471 
1472 PIPELINE graphics my_pipeline
1473   ATTACH my_shader
1474   ATTACH my_fragment
1475 
1476   BIND BUFFER my_buf AS uniform DESCRIPTOR_SET 1
1477 END)";
1478 
1479   Parser parser;
1480   Result r = parser.Parse(in);
1481   ASSERT_FALSE(r.IsSuccess());
1482   EXPECT_EQ("13: missing BINDING for BIND command", r.Error());
1483 }
1484 
TEST_F(AmberScriptParserTest,BindBufferMissingDescriptorSetValue)1485 TEST_F(AmberScriptParserTest, BindBufferMissingDescriptorSetValue) {
1486   std::string in = R"(
1487 SHADER vertex my_shader PASSTHROUGH
1488 SHADER fragment my_fragment GLSL
1489 # GLSL Shader
1490 END
1491 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
1492 
1493 PIPELINE graphics my_pipeline
1494   ATTACH my_shader
1495   ATTACH my_fragment
1496 
1497   BIND BUFFER my_buf AS uniform DESCRIPTOR_SET BINDING 2
1498 END)";
1499 
1500   Parser parser;
1501   Result r = parser.Parse(in);
1502   ASSERT_FALSE(r.IsSuccess());
1503   EXPECT_EQ("12: invalid value for DESCRIPTOR_SET in BIND command", r.Error());
1504 }
1505 
TEST_F(AmberScriptParserTest,BindBufferMissingDescriptorSet)1506 TEST_F(AmberScriptParserTest, BindBufferMissingDescriptorSet) {
1507   std::string in = R"(
1508 SHADER vertex my_shader PASSTHROUGH
1509 SHADER fragment my_fragment GLSL
1510 # GLSL Shader
1511 END
1512 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
1513 
1514 PIPELINE graphics my_pipeline
1515   ATTACH my_shader
1516   ATTACH my_fragment
1517 
1518   BIND BUFFER my_buf AS uniform BINDING 2
1519 END)";
1520 
1521   Parser parser;
1522   Result r = parser.Parse(in);
1523   ASSERT_FALSE(r.IsSuccess());
1524   EXPECT_EQ("12: missing DESCRIPTOR_SET or KERNEL for BIND command", r.Error());
1525 }
1526 
TEST_F(AmberScriptParserTest,BindingBufferExtraParams)1527 TEST_F(AmberScriptParserTest, BindingBufferExtraParams) {
1528   std::string in = R"(
1529 SHADER vertex my_shader PASSTHROUGH
1530 SHADER fragment my_fragment GLSL
1531 # GLSL Shader
1532 END
1533 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
1534 
1535 PIPELINE graphics my_pipeline
1536   ATTACH my_shader
1537   ATTACH my_fragment
1538 
1539   BIND BUFFER my_buf AS uniform DESCRIPTOR_SET 1 BINDING 2 EXTRA
1540 END)";
1541 
1542   Parser parser;
1543   Result r = parser.Parse(in);
1544   ASSERT_FALSE(r.IsSuccess());
1545   EXPECT_EQ("12: extra parameters after BIND command: EXTRA", r.Error());
1546 }
1547 
TEST_F(AmberScriptParserTest,BindingBufferInvalidBindingValue)1548 TEST_F(AmberScriptParserTest, BindingBufferInvalidBindingValue) {
1549   std::string in = R"(
1550 SHADER vertex my_shader PASSTHROUGH
1551 SHADER fragment my_fragment GLSL
1552 # GLSL Shader
1553 END
1554 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
1555 
1556 PIPELINE graphics my_pipeline
1557   ATTACH my_shader
1558   ATTACH my_fragment
1559 
1560   BIND BUFFER my_buf AS uniform DESCRIPTOR_SET 1 BINDING INVALID
1561 END)";
1562 
1563   Parser parser;
1564   Result r = parser.Parse(in);
1565   ASSERT_FALSE(r.IsSuccess());
1566   EXPECT_EQ("12: invalid value for BINDING in BIND command", r.Error());
1567 }
1568 
TEST_F(AmberScriptParserTest,BindingBufferInvalidDescriptorSetValue)1569 TEST_F(AmberScriptParserTest, BindingBufferInvalidDescriptorSetValue) {
1570   std::string in = R"(
1571 SHADER vertex my_shader PASSTHROUGH
1572 SHADER fragment my_fragment GLSL
1573 # GLSL Shader
1574 END
1575 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
1576 
1577 PIPELINE graphics my_pipeline
1578   ATTACH my_shader
1579   ATTACH my_fragment
1580 
1581   BIND BUFFER my_buf AS uniform DESCRIPTOR_SET INVALID BINDING 2
1582 END)";
1583 
1584   Parser parser;
1585   Result r = parser.Parse(in);
1586   ASSERT_FALSE(r.IsSuccess());
1587   EXPECT_EQ("12: invalid value for DESCRIPTOR_SET in BIND command", r.Error());
1588 }
1589 
TEST_F(AmberScriptParserTest,BindingBufferInvalidBufferType)1590 TEST_F(AmberScriptParserTest, BindingBufferInvalidBufferType) {
1591   std::string in = R"(
1592 SHADER vertex my_shader PASSTHROUGH
1593 SHADER fragment my_fragment GLSL
1594 # GLSL Shader
1595 END
1596 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
1597 
1598 PIPELINE graphics my_pipeline
1599   ATTACH my_shader
1600   ATTACH my_fragment
1601 
1602   BIND BUFFER my_buf AS INVALID DESCRIPTOR_SET 1 BINDING 2
1603 END)";
1604 
1605   Parser parser;
1606   Result r = parser.Parse(in);
1607   ASSERT_FALSE(r.IsSuccess());
1608   EXPECT_EQ("12: unknown buffer_type: INVALID", r.Error());
1609 }
1610 
1611 struct BufferTypeData {
1612   const char* name;
1613   BufferType type;
1614 };
1615 
1616 using AmberScriptParserBufferTypeTest = testing::TestWithParam<BufferTypeData>;
TEST_P(AmberScriptParserBufferTypeTest,BufferType)1617 TEST_P(AmberScriptParserBufferTypeTest, BufferType) {
1618   auto test_data = GetParam();
1619 
1620   std::string in = R"(
1621 SHADER vertex my_shader PASSTHROUGH
1622 SHADER fragment my_fragment GLSL
1623 # GLSL Shader
1624 END
1625 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
1626 
1627 PIPELINE graphics my_pipeline
1628   ATTACH my_shader
1629   ATTACH my_fragment
1630 
1631   BIND BUFFER my_buf AS )" +
1632                    std::string(test_data.name) +
1633                    " DESCRIPTOR_SET 0 BINDING 0\nEND";
1634 
1635   Parser parser;
1636   Result r = parser.Parse(in);
1637   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1638 
1639   auto script = parser.GetScript();
1640   const auto& pipelines = script->GetPipelines();
1641   ASSERT_EQ(1U, pipelines.size());
1642 
1643   const auto* pipeline = pipelines[0].get();
1644   const auto& bufs = pipeline->GetBuffers();
1645   ASSERT_EQ(1U, bufs.size());
1646   EXPECT_EQ(test_data.type, bufs[0].type);
1647 }
1648 INSTANTIATE_TEST_SUITE_P(
1649     AmberScriptParserBufferTypeTestSamples,
1650     AmberScriptParserBufferTypeTest,
1651     testing::Values(BufferTypeData{"uniform", BufferType::kUniform},
1652                     BufferTypeData{
1653                         "storage",
1654                         BufferType::kStorage}));  // NOLINT(whitespace/parens)
1655 
TEST_F(AmberScriptParserTest,BindPushConstants)1656 TEST_F(AmberScriptParserTest, BindPushConstants) {
1657   std::string in = R"(
1658 SHADER vertex my_shader PASSTHROUGH
1659 SHADER fragment my_fragment GLSL
1660 # GLSL Shader
1661 END
1662 BUFFER my_buf DATA_TYPE float SIZE 20 FILL 5
1663 
1664 PIPELINE graphics my_pipeline
1665   ATTACH my_shader
1666   ATTACH my_fragment
1667 
1668   BIND BUFFER my_buf AS push_constant
1669 END)";
1670 
1671   Parser parser;
1672   Result r = parser.Parse(in);
1673   ASSERT_TRUE(r.IsSuccess()) << r.Error();
1674 
1675   auto script = parser.GetScript();
1676   const auto& pipelines = script->GetPipelines();
1677   ASSERT_EQ(1U, pipelines.size());
1678 
1679   const auto* pipeline = pipelines[0].get();
1680   const auto& buf = pipeline->GetPushConstantBuffer();
1681   ASSERT_TRUE(buf.buffer != nullptr);
1682   EXPECT_EQ(20u, buf.buffer->ElementCount());
1683   EXPECT_EQ(20u, buf.buffer->ValueCount());
1684   EXPECT_EQ(20u * sizeof(float), buf.buffer->GetSizeInBytes());
1685 }
1686 
TEST_F(AmberScriptParserTest,BindPushConstantsExtraParams)1687 TEST_F(AmberScriptParserTest, BindPushConstantsExtraParams) {
1688   std::string in = R"(
1689 SHADER vertex my_shader PASSTHROUGH
1690 SHADER fragment my_fragment GLSL
1691 # GLSL Shader
1692 END
1693 BUFFER my_buf DATA_TYPE float SIZE 20 FILL 5
1694 
1695 PIPELINE graphics my_pipeline
1696   ATTACH my_shader
1697   ATTACH my_fragment
1698 
1699   BIND BUFFER my_buf AS push_constant EXTRA
1700 END)";
1701 
1702   Parser parser;
1703   Result r = parser.Parse(in);
1704   ASSERT_FALSE(r.IsSuccess());
1705   EXPECT_EQ("12: extra parameters after BIND command: EXTRA", r.Error());
1706 }
1707 
TEST_F(AmberScriptParserTest,BindBufferOpenCLArgName)1708 TEST_F(AmberScriptParserTest, BindBufferOpenCLArgName) {
1709   std::string in = R"(
1710 SHADER compute my_shader OPENCL-C
1711 #shader
1712 END
1713 BUFFER my_buf DATA_TYPE uint32 DATA 1 END
1714 
1715 PIPELINE compute my_pipeline
1716   ATTACH my_shader
1717   BIND BUFFER my_buf AS storage KERNEL ARG_NAME arg
1718 END)";
1719 
1720   Parser parser;
1721   Result r = parser.Parse(in);
1722   ASSERT_TRUE(r.IsSuccess());
1723 }
1724 
TEST_F(AmberScriptParserTest,BindBufferOpenCLArgNumber)1725 TEST_F(AmberScriptParserTest, BindBufferOpenCLArgNumber) {
1726   std::string in = R"(
1727 SHADER compute my_shader OPENCL-C
1728 #shader
1729 END
1730 BUFFER my_buf DATA_TYPE uint32 DATA 1 END
1731 
1732 PIPELINE compute my_pipeline
1733   ATTACH my_shader
1734   BIND BUFFER my_buf AS storage KERNEL ARG_NUMBER 0
1735 END)";
1736 
1737   Parser parser;
1738   Result r = parser.Parse(in);
1739   ASSERT_TRUE(r.IsSuccess());
1740 }
1741 
TEST_F(AmberScriptParserTest,BindBufferOpenCLArgNameTypeless)1742 TEST_F(AmberScriptParserTest, BindBufferOpenCLArgNameTypeless) {
1743   std::string in = R"(
1744 SHADER compute my_shader OPENCL-C
1745 #shader
1746 END
1747 BUFFER my_buf DATA_TYPE uint32 DATA 1 END
1748 
1749 PIPELINE compute my_pipeline
1750   ATTACH my_shader
1751   BIND BUFFER my_buf KERNEL ARG_NAME arg
1752 END)";
1753 
1754   Parser parser;
1755   Result r = parser.Parse(in);
1756   ASSERT_TRUE(r.IsSuccess());
1757 }
1758 
TEST_F(AmberScriptParserTest,BindBufferOpenCLArgNumberTypeless)1759 TEST_F(AmberScriptParserTest, BindBufferOpenCLArgNumberTypeless) {
1760   std::string in = R"(
1761 SHADER compute my_shader OPENCL-C
1762 #shader
1763 END
1764 BUFFER my_buf DATA_TYPE uint32 DATA 1 END
1765 
1766 PIPELINE compute my_pipeline
1767   ATTACH my_shader
1768   BIND BUFFER my_buf KERNEL ARG_NUMBER 0
1769 END)";
1770 
1771   Parser parser;
1772   Result r = parser.Parse(in);
1773   ASSERT_TRUE(r.IsSuccess());
1774 }
1775 
TEST_F(AmberScriptParserTest,BindBufferOpenCLMissingKernel)1776 TEST_F(AmberScriptParserTest, BindBufferOpenCLMissingKernel) {
1777   std::string in = R"(
1778 SHADER compute my_shader OPENCL-C
1779 #shader
1780 END
1781 BUFFER my_buf DATA_TYPE uint32 DATA 1 END
1782 
1783 PIPELINE compute my_pipeline
1784   ATTACH my_shader
1785   BIND BUFFER my_buf AS storage ARG_NAME arg
1786 END)";
1787 
1788   Parser parser;
1789   Result r = parser.Parse(in);
1790   ASSERT_FALSE(r.IsSuccess());
1791   EXPECT_EQ("9: missing DESCRIPTOR_SET or KERNEL for BIND command", r.Error());
1792 }
1793 
TEST_F(AmberScriptParserTest,BindBufferOpenCLMissingArg)1794 TEST_F(AmberScriptParserTest, BindBufferOpenCLMissingArg) {
1795   std::string in = R"(
1796 SHADER compute my_shader OPENCL-C
1797 #shader
1798 END
1799 BUFFER my_buf DATA_TYPE uint32 DATA 1 END
1800 
1801 PIPELINE compute my_pipeline
1802   ATTACH my_shader
1803   BIND BUFFER my_buf AS storage KERNEL arg
1804 END)";
1805 
1806   Parser parser;
1807   Result r = parser.Parse(in);
1808   ASSERT_FALSE(r.IsSuccess());
1809   EXPECT_EQ("9: missing ARG_NAME or ARG_NUMBER keyword", r.Error());
1810 }
1811 
TEST_F(AmberScriptParserTest,BindBufferOpenCLMissingArgName)1812 TEST_F(AmberScriptParserTest, BindBufferOpenCLMissingArgName) {
1813   std::string in = R"(
1814 SHADER compute my_shader OPENCL-C
1815 #shader
1816 END
1817 BUFFER my_buf DATA_TYPE uint32 DATA 1 END
1818 
1819 PIPELINE compute my_pipeline
1820   ATTACH my_shader
1821   BIND BUFFER my_buf KERNEL ARG_NAME
1822 END)";
1823 
1824   Parser parser;
1825   Result r = parser.Parse(in);
1826   ASSERT_FALSE(r.IsSuccess());
1827   EXPECT_EQ("10: expected argument identifier", r.Error());
1828 }
1829 
TEST_F(AmberScriptParserTest,BindBufferOpenCLMissingArgNumber)1830 TEST_F(AmberScriptParserTest, BindBufferOpenCLMissingArgNumber) {
1831   std::string in = R"(
1832 SHADER compute my_shader OPENCL-C
1833 #shader
1834 END
1835 BUFFER my_buf DATA_TYPE uint32 DATA 1 END
1836 
1837 PIPELINE compute my_pipeline
1838   ATTACH my_shader
1839   BIND BUFFER my_buf AS storage KERNEL ARG_NUMBER
1840 END)";
1841 
1842   Parser parser;
1843   Result r = parser.Parse(in);
1844   ASSERT_FALSE(r.IsSuccess());
1845   EXPECT_EQ("10: expected argument number", r.Error());
1846 }
1847 
TEST_F(AmberScriptParserTest,BindBufferOpenCLArgNameNotString)1848 TEST_F(AmberScriptParserTest, BindBufferOpenCLArgNameNotString) {
1849   std::string in = R"(
1850 SHADER compute my_shader OPENCL-C
1851 #shader
1852 END
1853 BUFFER my_buf DATA_TYPE uint32 DATA 1 END
1854 
1855 PIPELINE compute my_pipeline
1856   ATTACH my_shader
1857   BIND BUFFER my_buf AS storage KERNEL ARG_NAME 0
1858 END)";
1859 
1860   Parser parser;
1861   Result r = parser.Parse(in);
1862   ASSERT_FALSE(r.IsSuccess());
1863   EXPECT_EQ("9: expected argument identifier", r.Error());
1864 }
1865 
TEST_F(AmberScriptParserTest,BindBufferOpenCLArgNumberNotInteger)1866 TEST_F(AmberScriptParserTest, BindBufferOpenCLArgNumberNotInteger) {
1867   std::string in = R"(
1868 SHADER compute my_shader OPENCL-C
1869 #shader
1870 END
1871 BUFFER my_buf DATA_TYPE uint32 DATA 1 END
1872 
1873 PIPELINE compute my_pipeline
1874   ATTACH my_shader
1875   BIND BUFFER my_buf KERNEL ARG_NUMBER in
1876 END)";
1877 
1878   Parser parser;
1879   Result r = parser.Parse(in);
1880   ASSERT_FALSE(r.IsSuccess());
1881   EXPECT_EQ("9: expected argument number", r.Error());
1882 }
1883 
TEST_F(AmberScriptParserTest,BindSamplerOpenCLMissingKernel)1884 TEST_F(AmberScriptParserTest, BindSamplerOpenCLMissingKernel) {
1885   std::string in = R"(
1886 SHADER compute my_shader OPENCL-C
1887 #shader
1888 END
1889 SAMPLER s
1890 
1891 PIPELINE compute my_pipeline
1892   ATTACH my_shader
1893   BIND SAMPLER s
1894 END
1895 )";
1896 
1897   Parser parser;
1898   Result r = parser.Parse(in);
1899   ASSERT_FALSE(r.IsSuccess());
1900   EXPECT_EQ("10: expected a string token for BIND command", r.Error());
1901 }
1902 
TEST_F(AmberScriptParserTest,BindSamplerOpenCLInvalidKernel)1903 TEST_F(AmberScriptParserTest, BindSamplerOpenCLInvalidKernel) {
1904   std::string in = R"(
1905 SHADER compute my_shader OPENCL-C
1906 #shader
1907 END
1908 SAMPLER s
1909 
1910 PIPELINE compute my_pipeline
1911   ATTACH my_shader
1912   BIND SAMPLER s INVALID
1913 END
1914 )";
1915 
1916   Parser parser;
1917   Result r = parser.Parse(in);
1918   ASSERT_FALSE(r.IsSuccess());
1919   EXPECT_EQ("9: missing DESCRIPTOR_SET or KERNEL for BIND command", r.Error());
1920 }
1921 
TEST_F(AmberScriptParserTest,BindSamplerOpenCLMissingArgument)1922 TEST_F(AmberScriptParserTest, BindSamplerOpenCLMissingArgument) {
1923   std::string in = R"(
1924 SHADER compute my_shader OPENCL-C
1925 #shader
1926 END
1927 SAMPLER s
1928 
1929 PIPELINE compute my_pipeline
1930   ATTACH my_shader
1931   BIND SAMPLER s KERNEL
1932 END
1933 )";
1934 
1935   Parser parser;
1936   Result r = parser.Parse(in);
1937   ASSERT_FALSE(r.IsSuccess());
1938   EXPECT_EQ("10: missing kernel arg identifier", r.Error());
1939 }
1940 
TEST_F(AmberScriptParserTest,BindSamplerOpenCLMissingArgumentName)1941 TEST_F(AmberScriptParserTest, BindSamplerOpenCLMissingArgumentName) {
1942   std::string in = R"(
1943 SHADER compute my_shader OPENCL-C
1944 #shader
1945 END
1946 SAMPLER s
1947 
1948 PIPELINE compute my_pipeline
1949   ATTACH my_shader
1950   BIND SAMPLER s KERNEL ARG_NAME
1951 END
1952 )";
1953 
1954   Parser parser;
1955   Result r = parser.Parse(in);
1956   ASSERT_FALSE(r.IsSuccess());
1957   EXPECT_EQ("10: expected argument identifier", r.Error());
1958 }
1959 
TEST_F(AmberScriptParserTest,BindSamplerOpenCLArgumentNameNotString)1960 TEST_F(AmberScriptParserTest, BindSamplerOpenCLArgumentNameNotString) {
1961   std::string in = R"(
1962 SHADER compute my_shader OPENCL-C
1963 #shader
1964 END
1965 SAMPLER s
1966 
1967 PIPELINE compute my_pipeline
1968   ATTACH my_shader
1969   BIND SAMPLER s KERNEL ARG_NAME 0
1970 END
1971 )";
1972 
1973   Parser parser;
1974   Result r = parser.Parse(in);
1975   ASSERT_FALSE(r.IsSuccess());
1976   EXPECT_EQ("9: expected argument identifier", r.Error());
1977 }
1978 
TEST_F(AmberScriptParserTest,BindSamplerOpenCLMissingArgumentNumber)1979 TEST_F(AmberScriptParserTest, BindSamplerOpenCLMissingArgumentNumber) {
1980   std::string in = R"(
1981 SHADER compute my_shader OPENCL-C
1982 #shader
1983 END
1984 SAMPLER s
1985 
1986 PIPELINE compute my_pipeline
1987   ATTACH my_shader
1988   BIND SAMPLER s KERNEL ARG_NUMBER
1989 END
1990 )";
1991 
1992   Parser parser;
1993   Result r = parser.Parse(in);
1994   ASSERT_FALSE(r.IsSuccess());
1995   EXPECT_EQ("10: expected argument number", r.Error());
1996 }
1997 
TEST_F(AmberScriptParserTest,BindSamplerOpenCLArgumentNumberNotInteger)1998 TEST_F(AmberScriptParserTest, BindSamplerOpenCLArgumentNumberNotInteger) {
1999   std::string in = R"(
2000 SHADER compute my_shader OPENCL-C
2001 #shader
2002 END
2003 SAMPLER s
2004 
2005 PIPELINE compute my_pipeline
2006   ATTACH my_shader
2007   BIND SAMPLER s KERNEL ARG_NUMBER a
2008 END
2009 )";
2010 
2011   Parser parser;
2012   Result r = parser.Parse(in);
2013   ASSERT_FALSE(r.IsSuccess());
2014   EXPECT_EQ("9: expected argument number", r.Error());
2015 }
2016 
TEST_F(AmberScriptParserTest,BindBufferStorageImageCompute)2017 TEST_F(AmberScriptParserTest, BindBufferStorageImageCompute) {
2018   std::string in = R"(
2019 SHADER compute compute_shader GLSL
2020 # GLSL Shader
2021 END
2022 
2023 BUFFER texture FORMAT R8G8B8A8_UNORM
2024 
2025 PIPELINE compute pipeline
2026   ATTACH compute_shader
2027   BIND BUFFER texture AS storage_image DESCRIPTOR_SET 0 BINDING 0
2028 END)";
2029 
2030   Parser parser;
2031   Result r = parser.Parse(in);
2032   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2033 
2034   auto script = parser.GetScript();
2035   const auto& pipelines = script->GetPipelines();
2036   ASSERT_EQ(1U, pipelines.size());
2037 
2038   const auto* pipeline = pipelines[0].get();
2039   const auto& bufs = pipeline->GetBuffers();
2040   ASSERT_EQ(1U, bufs.size());
2041   EXPECT_EQ(BufferType::kStorageImage, bufs[0].type);
2042 }
2043 
TEST_F(AmberScriptParserTest,BindBufferStorageImageGraphics)2044 TEST_F(AmberScriptParserTest, BindBufferStorageImageGraphics) {
2045   std::string in = R"(
2046 SHADER vertex vert_shader PASSTHROUGH
2047 SHADER fragment frag_shader GLSL
2048 # GLSL Shader
2049 END
2050 
2051 BUFFER texture FORMAT R8G8B8A8_UNORM
2052 BUFFER framebuffer FORMAT R8G8B8A8_UNORM
2053 
2054 PIPELINE graphics pipeline
2055   ATTACH vert_shader
2056   ATTACH frag_shader
2057   BIND BUFFER texture AS storage_image DESCRIPTOR_SET 0 BINDING 0
2058   BIND BUFFER framebuffer AS color LOCATION 0
2059 END)";
2060 
2061   Parser parser;
2062   Result r = parser.Parse(in);
2063   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2064 
2065   auto script = parser.GetScript();
2066   const auto& pipelines = script->GetPipelines();
2067   ASSERT_EQ(1U, pipelines.size());
2068 
2069   const auto* pipeline = pipelines[0].get();
2070   const auto& bufs = pipeline->GetBuffers();
2071   ASSERT_EQ(1U, bufs.size());
2072   EXPECT_EQ(BufferType::kStorageImage, bufs[0].type);
2073 }
2074 
TEST_F(AmberScriptParserTest,BindBufferStorageImageMissingDescriptorSetValue)2075 TEST_F(AmberScriptParserTest, BindBufferStorageImageMissingDescriptorSetValue) {
2076   std::string in = R"(
2077 SHADER compute compute_shader GLSL
2078 # GLSL Shader
2079 END
2080 
2081 BUFFER texture FORMAT R8G8B8A8_UNORM
2082 
2083 PIPELINE compute pipeline
2084   ATTACH compute_shader
2085   BIND BUFFER texture AS storage_image DESCRIPTOR_SET BINDING 0
2086 END)";
2087 
2088   Parser parser;
2089   Result r = parser.Parse(in);
2090   ASSERT_FALSE(r.IsSuccess());
2091   EXPECT_EQ("10: invalid value for DESCRIPTOR_SET in BIND command", r.Error());
2092 }
2093 
TEST_F(AmberScriptParserTest,BindBufferStorageImageMissingDescriptorSet)2094 TEST_F(AmberScriptParserTest, BindBufferStorageImageMissingDescriptorSet) {
2095   std::string in = R"(
2096 SHADER compute compute_shader GLSL
2097 # GLSL Shader
2098 END
2099 
2100 BUFFER texture FORMAT R8G8B8A8_UNORM
2101 
2102 PIPELINE compute pipeline
2103   ATTACH compute_shader
2104   BIND BUFFER texture AS storage_image BINDING 0
2105 END)";
2106 
2107   Parser parser;
2108   Result r = parser.Parse(in);
2109   ASSERT_FALSE(r.IsSuccess());
2110   EXPECT_EQ("10: missing DESCRIPTOR_SET or KERNEL for BIND command", r.Error());
2111 }
2112 
TEST_F(AmberScriptParserTest,BindBufferStorageImageMissingBindingValue)2113 TEST_F(AmberScriptParserTest, BindBufferStorageImageMissingBindingValue) {
2114   std::string in = R"(
2115 SHADER compute compute_shader GLSL
2116 # GLSL Shader
2117 END
2118 
2119 BUFFER texture FORMAT R8G8B8A8_UNORM
2120 
2121 PIPELINE compute pipeline
2122   ATTACH compute_shader
2123   BIND BUFFER texture AS storage_image DESCRIPTOR_SET 0 BINDING
2124 END)";
2125 
2126   Parser parser;
2127   Result r = parser.Parse(in);
2128   ASSERT_FALSE(r.IsSuccess());
2129   EXPECT_EQ("11: invalid value for BINDING in BIND command", r.Error());
2130 }
2131 
TEST_F(AmberScriptParserTest,BindBufferStorageImageMissingBinding)2132 TEST_F(AmberScriptParserTest, BindBufferStorageImageMissingBinding) {
2133   std::string in = R"(
2134 SHADER compute compute_shader GLSL
2135 # GLSL Shader
2136 END
2137 
2138 BUFFER texture FORMAT R8G8B8A8_UNORM
2139 
2140 PIPELINE compute pipeline
2141   ATTACH compute_shader
2142   BIND BUFFER texture AS storage_image DESCRIPTOR_SET 0
2143 END)";
2144 
2145   Parser parser;
2146   Result r = parser.Parse(in);
2147   ASSERT_FALSE(r.IsSuccess());
2148   EXPECT_EQ("11: missing BINDING for BIND command", r.Error());
2149 }
2150 
TEST_F(AmberScriptParserTest,BindBufferSampledImage)2151 TEST_F(AmberScriptParserTest, BindBufferSampledImage) {
2152   std::string in = R"(
2153 SHADER vertex vert_shader PASSTHROUGH
2154 SHADER fragment frag_shader GLSL
2155 # GLSL Shader
2156 END
2157 
2158 BUFFER texture FORMAT R8G8B8A8_UNORM
2159 BUFFER framebuffer FORMAT R8G8B8A8_UNORM
2160 
2161 PIPELINE graphics pipeline
2162   ATTACH vert_shader
2163   ATTACH frag_shader
2164   BIND BUFFER texture AS sampled_image DESCRIPTOR_SET 0 BINDING 0
2165   BIND BUFFER framebuffer AS color LOCATION 0
2166 END)";
2167 
2168   Parser parser;
2169   Result r = parser.Parse(in);
2170   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2171 
2172   auto script = parser.GetScript();
2173   const auto& pipelines = script->GetPipelines();
2174   ASSERT_EQ(1U, pipelines.size());
2175 
2176   const auto* pipeline = pipelines[0].get();
2177   const auto& bufs = pipeline->GetBuffers();
2178   ASSERT_EQ(1U, bufs.size());
2179   EXPECT_EQ(BufferType::kSampledImage, bufs[0].type);
2180 }
2181 
TEST_F(AmberScriptParserTest,BindBufferSampledImageMissingDescriptorSetValue)2182 TEST_F(AmberScriptParserTest, BindBufferSampledImageMissingDescriptorSetValue) {
2183   std::string in = R"(
2184 SHADER vertex vert_shader PASSTHROUGH
2185 SHADER fragment frag_shader GLSL
2186 # GLSL Shader
2187 END
2188 
2189 BUFFER texture FORMAT R8G8B8A8_UNORM
2190 
2191 PIPELINE graphics pipeline
2192   ATTACH vert_shader
2193   ATTACH frag_shader
2194   BIND BUFFER texture AS sampled_image DESCRIPTOR_SET BINDING 0
2195 END)";
2196 
2197   Parser parser;
2198   Result r = parser.Parse(in);
2199   ASSERT_FALSE(r.IsSuccess());
2200   EXPECT_EQ("12: invalid value for DESCRIPTOR_SET in BIND command", r.Error());
2201 }
2202 
TEST_F(AmberScriptParserTest,BindBufferSampledImageMissingDescriptorSet)2203 TEST_F(AmberScriptParserTest, BindBufferSampledImageMissingDescriptorSet) {
2204   std::string in = R"(
2205 SHADER vertex vert_shader PASSTHROUGH
2206 SHADER fragment frag_shader GLSL
2207 # GLSL Shader
2208 END
2209 
2210 BUFFER texture FORMAT R8G8B8A8_UNORM
2211 
2212 PIPELINE graphics pipeline
2213   ATTACH vert_shader
2214   ATTACH frag_shader
2215   BIND BUFFER texture AS sampled_image BINDING 0
2216 END)";
2217 
2218   Parser parser;
2219   Result r = parser.Parse(in);
2220   ASSERT_FALSE(r.IsSuccess());
2221   EXPECT_EQ("12: missing DESCRIPTOR_SET or KERNEL for BIND command", r.Error());
2222 }
2223 
TEST_F(AmberScriptParserTest,BindBufferSampledImageMissingBindingValue)2224 TEST_F(AmberScriptParserTest, BindBufferSampledImageMissingBindingValue) {
2225   std::string in = R"(
2226 SHADER vertex vert_shader PASSTHROUGH
2227 SHADER fragment frag_shader GLSL
2228 # GLSL Shader
2229 END
2230 
2231 BUFFER texture FORMAT R8G8B8A8_UNORM
2232 
2233 PIPELINE graphics pipeline
2234   ATTACH vert_shader
2235   ATTACH frag_shader
2236   BIND BUFFER texture AS sampled_image DESCRIPTOR_SET 0 BINDING
2237 END)";
2238 
2239   Parser parser;
2240   Result r = parser.Parse(in);
2241   ASSERT_FALSE(r.IsSuccess());
2242   EXPECT_EQ("13: invalid value for BINDING in BIND command", r.Error());
2243 }
2244 
TEST_F(AmberScriptParserTest,BindBufferSampledImageMissingBinding)2245 TEST_F(AmberScriptParserTest, BindBufferSampledImageMissingBinding) {
2246   std::string in = R"(
2247 SHADER vertex vert_shader PASSTHROUGH
2248 SHADER fragment frag_shader GLSL
2249 # GLSL Shader
2250 END
2251 
2252 BUFFER texture FORMAT R8G8B8A8_UNORM
2253 
2254 PIPELINE graphics pipeline
2255   ATTACH vert_shader
2256   ATTACH frag_shader
2257   BIND BUFFER texture AS sampled_image DESCRIPTOR_SET 0
2258 END)";
2259 
2260   Parser parser;
2261   Result r = parser.Parse(in);
2262   ASSERT_FALSE(r.IsSuccess());
2263   EXPECT_EQ("13: missing BINDING for BIND command", r.Error());
2264 }
2265 
TEST_F(AmberScriptParserTest,BindBufferCombinedImageSampler)2266 TEST_F(AmberScriptParserTest, BindBufferCombinedImageSampler) {
2267   std::string in = R"(
2268 SHADER vertex vert_shader PASSTHROUGH
2269 SHADER fragment frag_shader GLSL
2270 # GLSL Shader
2271 END
2272 
2273 BUFFER texture FORMAT R8G8B8A8_UNORM
2274 BUFFER framebuffer FORMAT R8G8B8A8_UNORM
2275 SAMPLER sampler
2276 
2277 PIPELINE graphics pipeline
2278   ATTACH vert_shader
2279   ATTACH frag_shader
2280   BIND BUFFER texture AS combined_image_sampler SAMPLER sampler DESCRIPTOR_SET 0 BINDING 0
2281   BIND BUFFER framebuffer AS color LOCATION 0
2282 END)";
2283 
2284   Parser parser;
2285   Result r = parser.Parse(in);
2286   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2287 
2288   auto script = parser.GetScript();
2289   const auto& pipelines = script->GetPipelines();
2290   ASSERT_EQ(1U, pipelines.size());
2291 
2292   const auto* pipeline = pipelines[0].get();
2293   const auto& bufs = pipeline->GetBuffers();
2294   ASSERT_EQ(1U, bufs.size());
2295   EXPECT_EQ(BufferType::kCombinedImageSampler, bufs[0].type);
2296 }
2297 
TEST_F(AmberScriptParserTest,BindBufferCombinedImageSamplerMissingDescriptorSetValue)2298 TEST_F(AmberScriptParserTest,
2299        BindBufferCombinedImageSamplerMissingDescriptorSetValue) {
2300   std::string in = R"(
2301 SHADER vertex vert_shader PASSTHROUGH
2302 SHADER fragment frag_shader GLSL
2303 # GLSL Shader
2304 END
2305 
2306 BUFFER texture FORMAT R8G8B8A8_UNORM
2307 SAMPLER sampler
2308 
2309 PIPELINE graphics pipeline
2310   ATTACH vert_shader
2311   ATTACH frag_shader
2312   BIND BUFFER texture AS combined_image_sampler SAMPLER sampler DESCRIPTOR_SET BINDING 0
2313 END)";
2314 
2315   Parser parser;
2316   Result r = parser.Parse(in);
2317   ASSERT_FALSE(r.IsSuccess());
2318   EXPECT_EQ("13: invalid value for DESCRIPTOR_SET in BIND command", r.Error());
2319 }
2320 
TEST_F(AmberScriptParserTest,BindBufferCombinedImageSamplerMissingDescriptorSet)2321 TEST_F(AmberScriptParserTest,
2322        BindBufferCombinedImageSamplerMissingDescriptorSet) {
2323   std::string in = R"(
2324 SHADER vertex vert_shader PASSTHROUGH
2325 SHADER fragment frag_shader GLSL
2326 # GLSL Shader
2327 END
2328 
2329 BUFFER texture FORMAT R8G8B8A8_UNORM
2330 SAMPLER sampler
2331 
2332 PIPELINE graphics pipeline
2333   ATTACH vert_shader
2334   ATTACH frag_shader
2335   BIND BUFFER texture AS combined_image_sampler SAMPLER sampler BINDING 0
2336 END)";
2337 
2338   Parser parser;
2339   Result r = parser.Parse(in);
2340   ASSERT_FALSE(r.IsSuccess());
2341   EXPECT_EQ("13: missing DESCRIPTOR_SET or KERNEL for BIND command", r.Error());
2342 }
2343 
TEST_F(AmberScriptParserTest,BindBufferCombinedImageSamplerMissingBindingValue)2344 TEST_F(AmberScriptParserTest,
2345        BindBufferCombinedImageSamplerMissingBindingValue) {
2346   std::string in = R"(
2347 SHADER vertex vert_shader PASSTHROUGH
2348 SHADER fragment frag_shader GLSL
2349 # GLSL Shader
2350 END
2351 
2352 BUFFER texture FORMAT R8G8B8A8_UNORM
2353 SAMPLER sampler
2354 
2355 PIPELINE graphics pipeline
2356   ATTACH vert_shader
2357   ATTACH frag_shader
2358   BIND BUFFER texture AS combined_image_sampler SAMPLER sampler DESCRIPTOR_SET 0 BINDING
2359 END)";
2360 
2361   Parser parser;
2362   Result r = parser.Parse(in);
2363   ASSERT_FALSE(r.IsSuccess());
2364   EXPECT_EQ("14: invalid value for BINDING in BIND command", r.Error());
2365 }
2366 
TEST_F(AmberScriptParserTest,BindBufferCombinedImageSamplerMissingBinding)2367 TEST_F(AmberScriptParserTest, BindBufferCombinedImageSamplerMissingBinding) {
2368   std::string in = R"(
2369 SHADER vertex vert_shader PASSTHROUGH
2370 SHADER fragment frag_shader GLSL
2371 # GLSL Shader
2372 END
2373 
2374 BUFFER texture FORMAT R8G8B8A8_UNORM
2375 SAMPLER sampler
2376 
2377 PIPELINE graphics pipeline
2378   ATTACH vert_shader
2379   ATTACH frag_shader
2380   BIND BUFFER texture AS combined_image_sampler SAMPLER sampler DESCRIPTOR_SET 0
2381 END)";
2382 
2383   Parser parser;
2384   Result r = parser.Parse(in);
2385   ASSERT_FALSE(r.IsSuccess());
2386   EXPECT_EQ("14: missing BINDING for BIND command", r.Error());
2387 }
2388 
TEST_F(AmberScriptParserTest,BindBufferCombinedImageSamplerMissingSampler)2389 TEST_F(AmberScriptParserTest, BindBufferCombinedImageSamplerMissingSampler) {
2390   std::string in = R"(
2391 SHADER vertex vert_shader PASSTHROUGH
2392 SHADER fragment frag_shader GLSL
2393 # GLSL Shader
2394 END
2395 
2396 BUFFER texture FORMAT R8G8B8A8_UNORM
2397 
2398 PIPELINE graphics pipeline
2399   ATTACH vert_shader
2400   ATTACH frag_shader
2401   BIND BUFFER texture AS combined_image_sampler DESCRIPTOR_SET 0 BINDING 0
2402 END)";
2403 
2404   Parser parser;
2405   Result r = parser.Parse(in);
2406   ASSERT_FALSE(r.IsSuccess());
2407   EXPECT_EQ("12: expecting SAMPLER for combined image sampler", r.Error());
2408 }
2409 
TEST_F(AmberScriptParserTest,BindBufferCombinedImageSamplerUnknownSampler)2410 TEST_F(AmberScriptParserTest, BindBufferCombinedImageSamplerUnknownSampler) {
2411   std::string in = R"(
2412 SHADER vertex vert_shader PASSTHROUGH
2413 SHADER fragment frag_shader GLSL
2414 # GLSL Shader
2415 END
2416 
2417 BUFFER texture FORMAT R8G8B8A8_UNORM
2418 
2419 PIPELINE graphics pipeline
2420   ATTACH vert_shader
2421   ATTACH frag_shader
2422   BIND BUFFER texture AS combined_image_sampler SAMPLER foo DESCRIPTOR_SET 0 BINDING 0
2423 END)";
2424 
2425   Parser parser;
2426   Result r = parser.Parse(in);
2427   ASSERT_FALSE(r.IsSuccess());
2428   EXPECT_EQ("12: unknown sampler: foo", r.Error());
2429 }
2430 
TEST_F(AmberScriptParserTest,BindBufferCombinedImageSamplerBaseMipLevel)2431 TEST_F(AmberScriptParserTest, BindBufferCombinedImageSamplerBaseMipLevel) {
2432   std::string in = R"(
2433 SHADER vertex vert_shader PASSTHROUGH
2434 SHADER fragment frag_shader GLSL
2435 # GLSL Shader
2436 END
2437 
2438 BUFFER texture FORMAT R8G8B8A8_UNORM MIP_LEVELS 4
2439 BUFFER framebuffer FORMAT R8G8B8A8_UNORM
2440 SAMPLER sampler MAX_LOD 4.0
2441 
2442 PIPELINE graphics pipeline
2443   ATTACH vert_shader
2444   ATTACH frag_shader
2445   BIND BUFFER texture AS combined_image_sampler SAMPLER sampler DESCRIPTOR_SET 0 BINDING 0 BASE_MIP_LEVEL 2
2446   BIND BUFFER framebuffer AS color LOCATION 0
2447 END)";
2448 
2449   Parser parser;
2450   Result r = parser.Parse(in);
2451   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2452 
2453   auto script = parser.GetScript();
2454   const auto& pipelines = script->GetPipelines();
2455   ASSERT_EQ(1U, pipelines.size());
2456 
2457   const auto* pipeline = pipelines[0].get();
2458   const auto& bufs = pipeline->GetBuffers();
2459   ASSERT_EQ(1U, bufs.size());
2460   EXPECT_EQ(2U, bufs[0].base_mip_level);
2461 }
2462 
TEST_F(AmberScriptParserTest,BindBufferCombinedImageSamplerMissingBaseMipLevel)2463 TEST_F(AmberScriptParserTest,
2464        BindBufferCombinedImageSamplerMissingBaseMipLevel) {
2465   std::string in = R"(
2466 SHADER vertex vert_shader PASSTHROUGH
2467 SHADER fragment frag_shader GLSL
2468 # GLSL Shader
2469 END
2470 
2471 BUFFER texture FORMAT R8G8B8A8_UNORM MIP_LEVELS 4
2472 BUFFER framebuffer FORMAT R8G8B8A8_UNORM
2473 SAMPLER sampler MAX_LOD 4.0
2474 
2475 PIPELINE graphics pipeline
2476   ATTACH vert_shader
2477   ATTACH frag_shader
2478   BIND BUFFER texture AS combined_image_sampler SAMPLER sampler DESCRIPTOR_SET 0 BINDING 0 BASE_MIP_LEVEL
2479   BIND BUFFER framebuffer AS color LOCATION 0
2480 END)";
2481 
2482   Parser parser;
2483   Result r = parser.Parse(in);
2484 
2485   ASSERT_FALSE(r.IsSuccess());
2486   EXPECT_EQ("15: invalid value for BASE_MIP_LEVEL", r.Error());
2487 }
2488 
TEST_F(AmberScriptParserTest,BindBufferCombinedImageSamplerBaseMipLevelTooLarge)2489 TEST_F(AmberScriptParserTest,
2490        BindBufferCombinedImageSamplerBaseMipLevelTooLarge) {
2491   std::string in = R"(
2492 SHADER vertex vert_shader PASSTHROUGH
2493 SHADER fragment frag_shader GLSL
2494 # GLSL Shader
2495 END
2496 
2497 BUFFER texture FORMAT R8G8B8A8_UNORM MIP_LEVELS 2
2498 BUFFER framebuffer FORMAT R8G8B8A8_UNORM
2499 SAMPLER sampler MAX_LOD 2.0
2500 
2501 PIPELINE graphics pipeline
2502   ATTACH vert_shader
2503   ATTACH frag_shader
2504   BIND BUFFER texture AS combined_image_sampler SAMPLER sampler DESCRIPTOR_SET 0 BINDING 0 BASE_MIP_LEVEL 3
2505   BIND BUFFER framebuffer AS color LOCATION 0
2506 END)";
2507 
2508   Parser parser;
2509   Result r = parser.Parse(in);
2510 
2511   ASSERT_FALSE(r.IsSuccess());
2512   EXPECT_EQ(
2513       "14: base mip level (now 3) needs to be larger than the number of buffer "
2514       "mip maps (2)",
2515       r.Error());
2516 }
2517 
TEST_F(AmberScriptParserTest,BindBufferUniformTexelBufferCompute)2518 TEST_F(AmberScriptParserTest, BindBufferUniformTexelBufferCompute) {
2519   std::string in = R"(
2520 SHADER compute compute_shader GLSL
2521 # GLSL Shader
2522 END
2523 
2524 BUFFER texture FORMAT R8G8B8A8_UNORM
2525 
2526 PIPELINE compute pipeline
2527   ATTACH compute_shader
2528   BIND BUFFER texture AS uniform_texel_buffer DESCRIPTOR_SET 0 BINDING 0
2529 END)";
2530 
2531   Parser parser;
2532   Result r = parser.Parse(in);
2533   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2534 
2535   auto script = parser.GetScript();
2536   const auto& pipelines = script->GetPipelines();
2537   ASSERT_EQ(1U, pipelines.size());
2538 
2539   const auto* pipeline = pipelines[0].get();
2540   const auto& bufs = pipeline->GetBuffers();
2541   ASSERT_EQ(1U, bufs.size());
2542   EXPECT_EQ(BufferType::kUniformTexelBuffer, bufs[0].type);
2543 }
2544 
TEST_F(AmberScriptParserTest,BindBufferUniformTexelBufferGraphics)2545 TEST_F(AmberScriptParserTest, BindBufferUniformTexelBufferGraphics) {
2546   std::string in = R"(
2547 SHADER vertex vert_shader PASSTHROUGH
2548 SHADER fragment frag_shader GLSL
2549 # GLSL Shader
2550 END
2551 
2552 BUFFER texture FORMAT R8G8B8A8_UNORM
2553 BUFFER framebuffer FORMAT R8G8B8A8_UNORM
2554 
2555 PIPELINE graphics pipeline
2556   ATTACH vert_shader
2557   ATTACH frag_shader
2558   BIND BUFFER texture AS uniform_texel_buffer DESCRIPTOR_SET 0 BINDING 0
2559   BIND BUFFER framebuffer AS color LOCATION 0
2560 END)";
2561 
2562   Parser parser;
2563   Result r = parser.Parse(in);
2564   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2565 
2566   auto script = parser.GetScript();
2567   const auto& pipelines = script->GetPipelines();
2568   ASSERT_EQ(1U, pipelines.size());
2569 
2570   const auto* pipeline = pipelines[0].get();
2571   const auto& bufs = pipeline->GetBuffers();
2572   ASSERT_EQ(1U, bufs.size());
2573   EXPECT_EQ(BufferType::kUniformTexelBuffer, bufs[0].type);
2574 }
2575 
TEST_F(AmberScriptParserTest,BindBufferUniformTexelBufferMissingDescriptorSetValue)2576 TEST_F(AmberScriptParserTest,
2577        BindBufferUniformTexelBufferMissingDescriptorSetValue) {
2578   std::string in = R"(
2579 SHADER compute compute_shader GLSL
2580 # GLSL Shader
2581 END
2582 
2583 BUFFER texture FORMAT R8G8B8A8_UNORM
2584 
2585 PIPELINE compute pipeline
2586   ATTACH compute_shader
2587   BIND BUFFER texture AS uniform_texel_buffer DESCRIPTOR_SET BINDING 0
2588 END)";
2589 
2590   Parser parser;
2591   Result r = parser.Parse(in);
2592   ASSERT_FALSE(r.IsSuccess());
2593   EXPECT_EQ("10: invalid value for DESCRIPTOR_SET in BIND command", r.Error());
2594 }
2595 
TEST_F(AmberScriptParserTest,BindBufferUniformTexelBufferMissingDescriptorSet)2596 TEST_F(AmberScriptParserTest,
2597        BindBufferUniformTexelBufferMissingDescriptorSet) {
2598   std::string in = R"(
2599 SHADER compute compute_shader GLSL
2600 # GLSL Shader
2601 END
2602 
2603 BUFFER texture FORMAT R8G8B8A8_UNORM
2604 
2605 PIPELINE compute pipeline
2606   ATTACH compute_shader
2607   BIND BUFFER texture AS uniform_texel_buffer BINDING 0
2608 END)";
2609 
2610   Parser parser;
2611   Result r = parser.Parse(in);
2612   ASSERT_FALSE(r.IsSuccess());
2613   EXPECT_EQ("10: missing DESCRIPTOR_SET or KERNEL for BIND command", r.Error());
2614 }
2615 
TEST_F(AmberScriptParserTest,BindBufferUniformTexelBufferMissingBindingValue)2616 TEST_F(AmberScriptParserTest, BindBufferUniformTexelBufferMissingBindingValue) {
2617   std::string in = R"(
2618 SHADER compute compute_shader GLSL
2619 # GLSL Shader
2620 END
2621 
2622 BUFFER texture FORMAT R8G8B8A8_UNORM
2623 
2624 PIPELINE compute pipeline
2625   ATTACH compute_shader
2626   BIND BUFFER texture AS uniform_texel_buffer DESCRIPTOR_SET 0 BINDING
2627 END)";
2628 
2629   Parser parser;
2630   Result r = parser.Parse(in);
2631   ASSERT_FALSE(r.IsSuccess());
2632   EXPECT_EQ("11: invalid value for BINDING in BIND command", r.Error());
2633 }
2634 
TEST_F(AmberScriptParserTest,BindBufferUniformTexelBufferMissingBinding)2635 TEST_F(AmberScriptParserTest, BindBufferUniformTexelBufferMissingBinding) {
2636   std::string in = R"(
2637 SHADER compute compute_shader GLSL
2638 # GLSL Shader
2639 END
2640 
2641 BUFFER texture FORMAT R8G8B8A8_UNORM
2642 
2643 PIPELINE compute pipeline
2644   ATTACH compute_shader
2645   BIND BUFFER texture AS uniform_texel_buffer DESCRIPTOR_SET 0
2646 END)";
2647 
2648   Parser parser;
2649   Result r = parser.Parse(in);
2650   ASSERT_FALSE(r.IsSuccess());
2651   EXPECT_EQ("11: missing BINDING for BIND command", r.Error());
2652 }
2653 
TEST_F(AmberScriptParserTest,BindBufferStorageTexelBufferCompute)2654 TEST_F(AmberScriptParserTest, BindBufferStorageTexelBufferCompute) {
2655   std::string in = R"(
2656 SHADER compute compute_shader GLSL
2657 # GLSL Shader
2658 END
2659 
2660 BUFFER texture FORMAT R8G8B8A8_UNORM
2661 
2662 PIPELINE compute pipeline
2663   ATTACH compute_shader
2664   BIND BUFFER texture AS storage_texel_buffer DESCRIPTOR_SET 0 BINDING 0
2665 END)";
2666 
2667   Parser parser;
2668   Result r = parser.Parse(in);
2669   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2670 
2671   auto script = parser.GetScript();
2672   const auto& pipelines = script->GetPipelines();
2673   ASSERT_EQ(1U, pipelines.size());
2674 
2675   const auto* pipeline = pipelines[0].get();
2676   const auto& bufs = pipeline->GetBuffers();
2677   ASSERT_EQ(1U, bufs.size());
2678   EXPECT_EQ(BufferType::kStorageTexelBuffer, bufs[0].type);
2679 }
2680 
TEST_F(AmberScriptParserTest,BindBufferStorageTexelBufferGraphics)2681 TEST_F(AmberScriptParserTest, BindBufferStorageTexelBufferGraphics) {
2682   std::string in = R"(
2683 SHADER vertex vert_shader PASSTHROUGH
2684 SHADER fragment frag_shader GLSL
2685 # GLSL Shader
2686 END
2687 
2688 BUFFER texture FORMAT R8G8B8A8_UNORM
2689 BUFFER framebuffer FORMAT R8G8B8A8_UNORM
2690 
2691 PIPELINE graphics pipeline
2692   ATTACH vert_shader
2693   ATTACH frag_shader
2694   BIND BUFFER texture AS storage_texel_buffer DESCRIPTOR_SET 0 BINDING 0
2695   BIND BUFFER framebuffer AS color LOCATION 0
2696 END)";
2697 
2698   Parser parser;
2699   Result r = parser.Parse(in);
2700   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2701 
2702   auto script = parser.GetScript();
2703   const auto& pipelines = script->GetPipelines();
2704   ASSERT_EQ(1U, pipelines.size());
2705 
2706   const auto* pipeline = pipelines[0].get();
2707   const auto& bufs = pipeline->GetBuffers();
2708   ASSERT_EQ(1U, bufs.size());
2709   EXPECT_EQ(BufferType::kStorageTexelBuffer, bufs[0].type);
2710 }
2711 
TEST_F(AmberScriptParserTest,BindBufferStorageTexelBufferMissingDescriptorSetValue)2712 TEST_F(AmberScriptParserTest,
2713        BindBufferStorageTexelBufferMissingDescriptorSetValue) {
2714   std::string in = R"(
2715 SHADER compute compute_shader GLSL
2716 # GLSL Shader
2717 END
2718 
2719 BUFFER texture FORMAT R8G8B8A8_UNORM
2720 
2721 PIPELINE compute pipeline
2722   ATTACH compute_shader
2723   BIND BUFFER texture AS storage_texel_buffer DESCRIPTOR_SET BINDING 0
2724 END)";
2725 
2726   Parser parser;
2727   Result r = parser.Parse(in);
2728   ASSERT_FALSE(r.IsSuccess());
2729   EXPECT_EQ("10: invalid value for DESCRIPTOR_SET in BIND command", r.Error());
2730 }
2731 
TEST_F(AmberScriptParserTest,BindBufferStorageTexelBufferMissingDescriptorSet)2732 TEST_F(AmberScriptParserTest,
2733        BindBufferStorageTexelBufferMissingDescriptorSet) {
2734   std::string in = R"(
2735 SHADER compute compute_shader GLSL
2736 # GLSL Shader
2737 END
2738 
2739 BUFFER texture FORMAT R8G8B8A8_UNORM
2740 
2741 PIPELINE compute pipeline
2742   ATTACH compute_shader
2743   BIND BUFFER texture AS storage_texel_buffer BINDING 0
2744 END)";
2745 
2746   Parser parser;
2747   Result r = parser.Parse(in);
2748   ASSERT_FALSE(r.IsSuccess());
2749   EXPECT_EQ("10: missing DESCRIPTOR_SET or KERNEL for BIND command", r.Error());
2750 }
2751 
TEST_F(AmberScriptParserTest,BindBufferStorageTexelBufferMissingBindingValue)2752 TEST_F(AmberScriptParserTest, BindBufferStorageTexelBufferMissingBindingValue) {
2753   std::string in = R"(
2754 SHADER compute compute_shader GLSL
2755 # GLSL Shader
2756 END
2757 
2758 BUFFER texture FORMAT R8G8B8A8_UNORM
2759 
2760 PIPELINE compute pipeline
2761   ATTACH compute_shader
2762   BIND BUFFER texture AS storage_texel_buffer DESCRIPTOR_SET 0 BINDING
2763 END)";
2764 
2765   Parser parser;
2766   Result r = parser.Parse(in);
2767   ASSERT_FALSE(r.IsSuccess());
2768   EXPECT_EQ("11: invalid value for BINDING in BIND command", r.Error());
2769 }
2770 
TEST_F(AmberScriptParserTest,BindBufferStorageTexelBufferMissingBinding)2771 TEST_F(AmberScriptParserTest, BindBufferStorageTexelBufferMissingBinding) {
2772   std::string in = R"(
2773 SHADER compute compute_shader GLSL
2774 # GLSL Shader
2775 END
2776 
2777 BUFFER texture FORMAT R8G8B8A8_UNORM
2778 
2779 PIPELINE compute pipeline
2780   ATTACH compute_shader
2781   BIND BUFFER texture AS storage_texel_buffer DESCRIPTOR_SET 0
2782 END)";
2783 
2784   Parser parser;
2785   Result r = parser.Parse(in);
2786   ASSERT_FALSE(r.IsSuccess());
2787   EXPECT_EQ("11: missing BINDING for BIND command", r.Error());
2788 }
2789 
TEST_F(AmberScriptParserTest,BindSampler)2790 TEST_F(AmberScriptParserTest, BindSampler) {
2791   std::string in = R"(
2792 SHADER vertex vert_shader PASSTHROUGH
2793 SHADER fragment frag_shader GLSL
2794 # GLSL Shader
2795 END
2796 
2797 SAMPLER sampler
2798 BUFFER framebuffer FORMAT R8G8B8A8_UNORM
2799 
2800 PIPELINE graphics pipeline
2801   ATTACH vert_shader
2802   ATTACH frag_shader
2803   BIND SAMPLER sampler DESCRIPTOR_SET 0 BINDING 0
2804   BIND BUFFER framebuffer AS color LOCATION 0
2805 END)";
2806 
2807   Parser parser;
2808   Result r = parser.Parse(in);
2809   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2810 
2811   auto script = parser.GetScript();
2812   const auto& pipelines = script->GetPipelines();
2813   ASSERT_EQ(1U, pipelines.size());
2814 
2815   const auto* pipeline = pipelines[0].get();
2816   const auto& samplers = pipeline->GetSamplers();
2817   ASSERT_EQ(1U, samplers.size());
2818 }
2819 
TEST_F(AmberScriptParserTest,BindSamplerMissingDescriptorSetValue)2820 TEST_F(AmberScriptParserTest, BindSamplerMissingDescriptorSetValue) {
2821   std::string in = R"(
2822 SHADER vertex vert_shader PASSTHROUGH
2823 SHADER fragment frag_shader GLSL
2824 # GLSL Shader
2825 END
2826 
2827 SAMPLER sampler
2828 
2829 PIPELINE graphics pipeline
2830   ATTACH vert_shader
2831   ATTACH frag_shader
2832   BIND SAMPLER sampler DESCRIPTOR_SET BINDING 0
2833 END)";
2834 
2835   Parser parser;
2836   Result r = parser.Parse(in);
2837   ASSERT_FALSE(r.IsSuccess());
2838   EXPECT_EQ("12: invalid value for DESCRIPTOR_SET in BIND command", r.Error());
2839 }
2840 
TEST_F(AmberScriptParserTest,BindSamplerMissingDescriptorSet)2841 TEST_F(AmberScriptParserTest, BindSamplerMissingDescriptorSet) {
2842   std::string in = R"(
2843 SHADER vertex vert_shader PASSTHROUGH
2844 SHADER fragment frag_shader GLSL
2845 # GLSL Shader
2846 END
2847 
2848 SAMPLER sampler
2849 
2850 PIPELINE graphics pipeline
2851   ATTACH vert_shader
2852   ATTACH frag_shader
2853   BIND SAMPLER sampler BINDING 0
2854 END)";
2855 
2856   Parser parser;
2857   Result r = parser.Parse(in);
2858   ASSERT_FALSE(r.IsSuccess());
2859   EXPECT_EQ("12: missing DESCRIPTOR_SET or KERNEL for BIND command", r.Error());
2860 }
2861 
TEST_F(AmberScriptParserTest,BindSamplerMissingBindingValue)2862 TEST_F(AmberScriptParserTest, BindSamplerMissingBindingValue) {
2863   std::string in = R"(
2864 SHADER vertex vert_shader PASSTHROUGH
2865 SHADER fragment frag_shader GLSL
2866 # GLSL Shader
2867 END
2868 
2869 SAMPLER sampler
2870 
2871 PIPELINE graphics pipeline
2872   ATTACH vert_shader
2873   ATTACH frag_shader
2874   BIND SAMPLER sampler DESCRIPTOR_SET 0 BINDING
2875 END)";
2876 
2877   Parser parser;
2878   Result r = parser.Parse(in);
2879   ASSERT_FALSE(r.IsSuccess());
2880   EXPECT_EQ("13: invalid value for BINDING in BIND command", r.Error());
2881 }
2882 
TEST_F(AmberScriptParserTest,BindSamplerMissingBinding)2883 TEST_F(AmberScriptParserTest, BindSamplerMissingBinding) {
2884   std::string in = R"(
2885 SHADER vertex vert_shader PASSTHROUGH
2886 SHADER fragment frag_shader GLSL
2887 # GLSL Shader
2888 END
2889 
2890 SAMPLER sampler
2891 
2892 PIPELINE graphics pipeline
2893   ATTACH vert_shader
2894   ATTACH frag_shader
2895   BIND SAMPLER sampler DESCRIPTOR_SET 0
2896 END)";
2897 
2898   Parser parser;
2899   Result r = parser.Parse(in);
2900   ASSERT_FALSE(r.IsSuccess());
2901   EXPECT_EQ("13: missing BINDING for BIND command", r.Error());
2902 }
2903 
TEST_F(AmberScriptParserTest,BindDescriptorOffsetWithUnsupportedBufferType)2904 TEST_F(AmberScriptParserTest, BindDescriptorOffsetWithUnsupportedBufferType) {
2905   std::string unsupported_buffer_types[] = {"uniform_texel_buffer",
2906                                             "storage_texel_buffer",
2907                                             "sampled_image", "storage_image"};
2908 
2909   for (const auto& buffer_type : unsupported_buffer_types) {
2910     std::ostringstream in;
2911     in << R"(
2912 SHADER compute compute_shader GLSL
2913 # GLSL Shader
2914 END
2915 
2916 BUFFER texture FORMAT R8G8B8A8_UNORM
2917 
2918 PIPELINE compute pipeline
2919   ATTACH compute_shader
2920   BIND BUFFER texture AS )"
2921        << buffer_type << R"( DESCRIPTOR_SET 0 BINDING 0 DESCRIPTOR_OFFSET 0
2922 END)";
2923     Parser parser;
2924     Result r = parser.Parse(in.str());
2925     ASSERT_FALSE(r.IsSuccess());
2926     EXPECT_EQ("10: extra parameters after BIND command: DESCRIPTOR_OFFSET",
2927               r.Error());
2928   }
2929 }
2930 
TEST_F(AmberScriptParserTest,BindBufferArray)2931 TEST_F(AmberScriptParserTest, BindBufferArray) {
2932   std::string in = R"(
2933 SHADER vertex my_shader PASSTHROUGH
2934 SHADER fragment my_fragment GLSL
2935 # GLSL Shader
2936 END
2937 BUFFER my_buf1 FORMAT R32G32B32A32_SFLOAT
2938 BUFFER my_buf2 FORMAT R32G32B32A32_SFLOAT
2939 
2940 PIPELINE graphics my_pipeline
2941   ATTACH my_shader
2942   ATTACH my_fragment
2943 
2944   BIND BUFFER_ARRAY my_buf1 my_buf2 AS uniform DESCRIPTOR_SET 1 BINDING 2
2945 END
2946 )";
2947 
2948   Parser parser;
2949   Result r = parser.Parse(in);
2950   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2951 
2952   auto script = parser.GetScript();
2953   const auto& pipelines = script->GetPipelines();
2954   ASSERT_EQ(1U, pipelines.size());
2955 
2956   const auto* pipeline = pipelines[0].get();
2957   const auto& bufs = pipeline->GetBuffers();
2958   ASSERT_EQ(2U, bufs.size());
2959   for (size_t i = 0; i < 2; i++) {
2960     EXPECT_EQ(BufferType::kUniform, bufs[i].type);
2961     EXPECT_EQ(1U, bufs[i].descriptor_set);
2962     EXPECT_EQ(2U, bufs[i].binding);
2963     EXPECT_EQ(0U, bufs[i].descriptor_offset);
2964     EXPECT_EQ(~0ULL, bufs[i].descriptor_range);
2965     EXPECT_EQ(static_cast<uint32_t>(0), bufs[i].location);
2966     EXPECT_EQ(FormatType::kR32G32B32A32_SFLOAT,
2967               bufs[i].buffer->GetFormat()->GetFormatType());
2968   }
2969 }
2970 
TEST_F(AmberScriptParserTest,BindBufferArrayWithDescriptorOffsetAndRange)2971 TEST_F(AmberScriptParserTest, BindBufferArrayWithDescriptorOffsetAndRange) {
2972   std::string in = R"(
2973 SHADER vertex my_shader PASSTHROUGH
2974 SHADER fragment my_fragment GLSL
2975 # GLSL Shader
2976 END
2977 BUFFER my_buf1 FORMAT R32G32B32A32_SFLOAT
2978 
2979 PIPELINE graphics my_pipeline
2980   ATTACH my_shader
2981   ATTACH my_fragment
2982 
2983   BIND BUFFER_ARRAY my_buf1 my_buf1 AS uniform DESCRIPTOR_SET 1 BINDING 2 DESCRIPTOR_OFFSET 256 512 DESCRIPTOR_RANGE 1024 2048
2984 END
2985 )";
2986 
2987   Parser parser;
2988   Result r = parser.Parse(in);
2989   ASSERT_TRUE(r.IsSuccess()) << r.Error();
2990 
2991   auto script = parser.GetScript();
2992   const auto& pipelines = script->GetPipelines();
2993   ASSERT_EQ(1U, pipelines.size());
2994 
2995   const auto* pipeline = pipelines[0].get();
2996   const auto& bufs = pipeline->GetBuffers();
2997   ASSERT_EQ(2U, bufs.size());
2998   for (size_t i = 0; i < 2; i++) {
2999     EXPECT_EQ(BufferType::kUniform, bufs[i].type);
3000     EXPECT_EQ(1U, bufs[i].descriptor_set);
3001     EXPECT_EQ(2U, bufs[i].binding);
3002     EXPECT_EQ(256U * (i + 1), bufs[i].descriptor_offset);
3003     EXPECT_EQ(1024U * (i + 1), bufs[i].descriptor_range);
3004     EXPECT_EQ(static_cast<uint32_t>(0), bufs[i].location);
3005     EXPECT_EQ(FormatType::kR32G32B32A32_SFLOAT,
3006               bufs[i].buffer->GetFormat()->GetFormatType());
3007   }
3008 }
3009 
TEST_F(AmberScriptParserTest,BindDynamicBufferArrayWithDescriptorOffsetAndRange)3010 TEST_F(AmberScriptParserTest,
3011        BindDynamicBufferArrayWithDescriptorOffsetAndRange) {
3012   std::string in = R"(
3013 SHADER vertex my_shader PASSTHROUGH
3014 SHADER fragment my_fragment GLSL
3015 # GLSL Shader
3016 END
3017 BUFFER my_buf1 FORMAT R32G32B32A32_SFLOAT
3018 
3019 PIPELINE graphics my_pipeline
3020   ATTACH my_shader
3021   ATTACH my_fragment
3022 
3023   BIND BUFFER_ARRAY my_buf1 my_buf1 AS uniform_dynamic DESCRIPTOR_SET 1 BINDING 2 OFFSET 16 32 DESCRIPTOR_OFFSET 256 512 DESCRIPTOR_RANGE 1024 2048
3024 END
3025 )";
3026 
3027   Parser parser;
3028   Result r = parser.Parse(in);
3029   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3030 
3031   auto script = parser.GetScript();
3032   const auto& pipelines = script->GetPipelines();
3033   ASSERT_EQ(1U, pipelines.size());
3034 
3035   const auto* pipeline = pipelines[0].get();
3036   const auto& bufs = pipeline->GetBuffers();
3037   ASSERT_EQ(2U, bufs.size());
3038   for (size_t i = 0; i < 2; i++) {
3039     EXPECT_EQ(BufferType::kUniformDynamic, bufs[i].type);
3040     EXPECT_EQ(1U, bufs[i].descriptor_set);
3041     EXPECT_EQ(2U, bufs[i].binding);
3042     EXPECT_EQ(16U * (i + 1), bufs[i].dynamic_offset);
3043     EXPECT_EQ(256U * (i + 1), bufs[i].descriptor_offset);
3044     EXPECT_EQ(1024U * (i + 1), bufs[i].descriptor_range);
3045     EXPECT_EQ(static_cast<uint32_t>(0), bufs[i].location);
3046     EXPECT_EQ(FormatType::kR32G32B32A32_SFLOAT,
3047               bufs[i].buffer->GetFormat()->GetFormatType());
3048   }
3049 }
3050 
TEST_F(AmberScriptParserTest,BindBufferArrayOnlyOneDescriptorOffset)3051 TEST_F(AmberScriptParserTest, BindBufferArrayOnlyOneDescriptorOffset) {
3052   std::string in = R"(
3053 SHADER vertex my_shader PASSTHROUGH
3054 SHADER fragment my_fragment GLSL
3055 # GLSL Shader
3056 END
3057 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
3058 
3059 PIPELINE graphics my_pipeline
3060   ATTACH my_shader
3061   ATTACH my_fragment
3062 
3063   BIND BUFFER_ARRAY my_buf my_buf AS uniform DESCRIPTOR_SET 1 BINDING 2 DESCRIPTOR_OFFSET 256
3064 END
3065 )";
3066 
3067   Parser parser;
3068   Result r = parser.Parse(in);
3069 
3070   ASSERT_FALSE(r.IsSuccess());
3071   EXPECT_EQ(
3072       "13: expecting a DESCRIPTOR_OFFSET value for each buffer in the array",
3073       r.Error());
3074 }
3075 
TEST_F(AmberScriptParserTest,BindBufferArrayOnlyOneDescriptorRange)3076 TEST_F(AmberScriptParserTest, BindBufferArrayOnlyOneDescriptorRange) {
3077   std::string in = R"(
3078 SHADER vertex my_shader PASSTHROUGH
3079 SHADER fragment my_fragment GLSL
3080 # GLSL Shader
3081 END
3082 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
3083 
3084 PIPELINE graphics my_pipeline
3085   ATTACH my_shader
3086   ATTACH my_fragment
3087 
3088   BIND BUFFER_ARRAY my_buf my_buf AS uniform DESCRIPTOR_SET 1 BINDING 2 DESCRIPTOR_RANGE 256
3089 END
3090 )";
3091 
3092   Parser parser;
3093   Result r = parser.Parse(in);
3094 
3095   ASSERT_FALSE(r.IsSuccess());
3096   EXPECT_EQ(
3097       "13: expecting a DESCRIPTOR_RANGE value for each buffer in the array",
3098       r.Error());
3099 }
3100 
TEST_F(AmberScriptParserTest,BindUniformBufferEmptyDescriptorOffset)3101 TEST_F(AmberScriptParserTest, BindUniformBufferEmptyDescriptorOffset) {
3102   std::string in = R"(
3103 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
3104 PIPELINE graphics my_pipeline
3105   BIND BUFFER my_buf AS uniform DESCRIPTOR_SET 1 BINDING 2 DESCRIPTOR_OFFSET
3106 END
3107 )";
3108 
3109   Parser parser;
3110   Result r = parser.Parse(in);
3111   ASSERT_FALSE(r.IsSuccess());
3112   EXPECT_EQ("5: expecting an integer value for DESCRIPTOR_OFFSET", r.Error());
3113 }
3114 
TEST_F(AmberScriptParserTest,BindUniformBufferInvalidDescriptorOffset)3115 TEST_F(AmberScriptParserTest, BindUniformBufferInvalidDescriptorOffset) {
3116   std::string in = R"(
3117 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
3118 PIPELINE graphics my_pipeline
3119   BIND BUFFER my_buf AS uniform DESCRIPTOR_SET 1 BINDING 2 DESCRIPTOR_OFFSET foo
3120 END
3121 )";
3122 
3123   Parser parser;
3124   Result r = parser.Parse(in);
3125   ASSERT_FALSE(r.IsSuccess());
3126   EXPECT_EQ("4: expecting an integer value for DESCRIPTOR_OFFSET", r.Error());
3127 }
3128 
TEST_F(AmberScriptParserTest,BindUniformBufferEmptyDescriptorRange)3129 TEST_F(AmberScriptParserTest, BindUniformBufferEmptyDescriptorRange) {
3130   std::string in = R"(
3131 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
3132 PIPELINE graphics my_pipeline
3133   BIND BUFFER my_buf AS uniform DESCRIPTOR_SET 1 BINDING 2 DESCRIPTOR_RANGE
3134 END
3135 )";
3136 
3137   Parser parser;
3138   Result r = parser.Parse(in);
3139   ASSERT_FALSE(r.IsSuccess());
3140   EXPECT_EQ("5: expecting an integer value for DESCRIPTOR_RANGE", r.Error());
3141 }
3142 
TEST_F(AmberScriptParserTest,BindUniformBufferInvalidDescriptorRange)3143 TEST_F(AmberScriptParserTest, BindUniformBufferInvalidDescriptorRange) {
3144   std::string in = R"(
3145 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
3146 PIPELINE graphics my_pipeline
3147   BIND BUFFER my_buf AS uniform DESCRIPTOR_SET 1 BINDING 2 DESCRIPTOR_RANGE foo
3148 END
3149 )";
3150 
3151   Parser parser;
3152   Result r = parser.Parse(in);
3153   ASSERT_FALSE(r.IsSuccess());
3154   EXPECT_EQ("4: expecting an integer value for DESCRIPTOR_RANGE", r.Error());
3155 }
3156 
TEST_F(AmberScriptParserTest,BindBufferArrayOnlyOneBuffer)3157 TEST_F(AmberScriptParserTest, BindBufferArrayOnlyOneBuffer) {
3158   std::string in = R"(
3159 SHADER vertex my_shader PASSTHROUGH
3160 SHADER fragment my_fragment GLSL
3161 # GLSL Shader
3162 END
3163 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
3164 
3165 PIPELINE graphics my_pipeline
3166   ATTACH my_shader
3167   ATTACH my_fragment
3168 
3169   BIND BUFFER_ARRAY my_buf AS uniform DESCRIPTOR_SET 1 BINDING 2
3170 END
3171 )";
3172 
3173   Parser parser;
3174   Result r = parser.Parse(in);
3175 
3176   ASSERT_FALSE(r.IsSuccess());
3177   EXPECT_EQ("12: expecting multiple buffer names for BUFFER_ARRAY", r.Error());
3178 }
3179 
TEST_F(AmberScriptParserTest,BindSamplerArray)3180 TEST_F(AmberScriptParserTest, BindSamplerArray) {
3181   std::string in = R"(
3182 SHADER vertex vert_shader PASSTHROUGH
3183 SHADER fragment frag_shader GLSL
3184 # GLSL Shader
3185 END
3186 
3187 SAMPLER sampler1
3188 SAMPLER sampler2
3189 BUFFER framebuffer FORMAT R8G8B8A8_UNORM
3190 
3191 PIPELINE graphics pipeline
3192   ATTACH vert_shader
3193   ATTACH frag_shader
3194   BIND SAMPLER_ARRAY sampler1 sampler2 DESCRIPTOR_SET 0 BINDING 0
3195   BIND BUFFER framebuffer AS color LOCATION 0
3196 END)";
3197 
3198   Parser parser;
3199   Result r = parser.Parse(in);
3200   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3201 
3202   auto script = parser.GetScript();
3203   const auto& pipelines = script->GetPipelines();
3204   ASSERT_EQ(1U, pipelines.size());
3205 
3206   const auto* pipeline = pipelines[0].get();
3207   const auto& samplers = pipeline->GetSamplers();
3208   ASSERT_EQ(2U, samplers.size());
3209 }
3210 
TEST_F(AmberScriptParserTest,BindSamplerArrayOnlyOneSampler)3211 TEST_F(AmberScriptParserTest, BindSamplerArrayOnlyOneSampler) {
3212   std::string in = R"(
3213 SHADER vertex my_shader PASSTHROUGH
3214 SHADER fragment my_fragment GLSL
3215 # GLSL Shader
3216 END
3217 SAMPLER sampler
3218 
3219 PIPELINE graphics my_pipeline
3220   ATTACH my_shader
3221   ATTACH my_fragment
3222 
3223   BIND SAMPLER_ARRAY sampler DESCRIPTOR_SET 1 BINDING 2
3224 END
3225 )";
3226 
3227   Parser parser;
3228   Result r = parser.Parse(in);
3229 
3230   ASSERT_FALSE(r.IsSuccess());
3231   EXPECT_EQ("12: expecting multiple sampler names for SAMPLER_ARRAY",
3232             r.Error());
3233 }
3234 
TEST_F(AmberScriptParserTest,BindUniformBufferDynamic)3235 TEST_F(AmberScriptParserTest, BindUniformBufferDynamic) {
3236   std::string in = R"(
3237 SHADER vertex my_shader PASSTHROUGH
3238 SHADER fragment my_fragment GLSL
3239 # GLSL Shader
3240 END
3241 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
3242 
3243 PIPELINE graphics my_pipeline
3244   ATTACH my_shader
3245   ATTACH my_fragment
3246 
3247   BIND BUFFER my_buf AS uniform_dynamic DESCRIPTOR_SET 1 BINDING 2 OFFSET 8
3248 END
3249 )";
3250 
3251   Parser parser;
3252   Result r = parser.Parse(in);
3253   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3254 
3255   auto script = parser.GetScript();
3256   const auto& pipelines = script->GetPipelines();
3257   ASSERT_EQ(1U, pipelines.size());
3258 
3259   const auto* pipeline = pipelines[0].get();
3260   const auto& bufs = pipeline->GetBuffers();
3261   ASSERT_EQ(1U, bufs.size());
3262   EXPECT_EQ(BufferType::kUniformDynamic, bufs[0].type);
3263   EXPECT_EQ(1U, bufs[0].descriptor_set);
3264   EXPECT_EQ(2U, bufs[0].binding);
3265   EXPECT_EQ(8u, bufs[0].dynamic_offset);
3266   EXPECT_EQ(static_cast<uint32_t>(0), bufs[0].location);
3267   EXPECT_EQ(FormatType::kR32G32B32A32_SFLOAT,
3268             bufs[0].buffer->GetFormat()->GetFormatType());
3269 }
3270 
TEST_F(AmberScriptParserTest,BindUniformBufferArrayDynamic)3271 TEST_F(AmberScriptParserTest, BindUniformBufferArrayDynamic) {
3272   std::string in = R"(
3273 SHADER vertex my_shader PASSTHROUGH
3274 SHADER fragment my_fragment GLSL
3275 # GLSL Shader
3276 END
3277 BUFFER buf0 FORMAT R32G32B32A32_SFLOAT
3278 BUFFER buf1 FORMAT R32G32B32A32_SFLOAT
3279 
3280 PIPELINE graphics my_pipeline
3281   ATTACH my_shader
3282   ATTACH my_fragment
3283 
3284   BIND BUFFER_ARRAY buf0 buf1 AS uniform_dynamic DESCRIPTOR_SET 1 BINDING 2 OFFSET 8 16
3285 END
3286 )";
3287 
3288   Parser parser;
3289   Result r = parser.Parse(in);
3290   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3291 
3292   auto script = parser.GetScript();
3293   const auto& pipelines = script->GetPipelines();
3294   ASSERT_EQ(1U, pipelines.size());
3295 
3296   const auto* pipeline = pipelines[0].get();
3297   const auto& bufs = pipeline->GetBuffers();
3298   ASSERT_EQ(2U, bufs.size());
3299   EXPECT_EQ(BufferType::kUniformDynamic, bufs[0].type);
3300   EXPECT_EQ(1U, bufs[0].descriptor_set);
3301   EXPECT_EQ(2U, bufs[0].binding);
3302   EXPECT_EQ(8u, bufs[0].dynamic_offset);
3303   EXPECT_EQ(static_cast<uint32_t>(0), bufs[0].location);
3304   EXPECT_EQ(FormatType::kR32G32B32A32_SFLOAT,
3305             bufs[0].buffer->GetFormat()->GetFormatType());
3306   EXPECT_EQ(1U, bufs[1].descriptor_set);
3307   EXPECT_EQ(2U, bufs[1].binding);
3308   EXPECT_EQ(16u, bufs[1].dynamic_offset);
3309   EXPECT_EQ(static_cast<uint32_t>(0), bufs[1].location);
3310   EXPECT_EQ(FormatType::kR32G32B32A32_SFLOAT,
3311             bufs[1].buffer->GetFormat()->GetFormatType());
3312 }
3313 
TEST_F(AmberScriptParserTest,BindUniformBufferDynamicMissingOffset)3314 TEST_F(AmberScriptParserTest, BindUniformBufferDynamicMissingOffset) {
3315   std::string in = R"(
3316 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
3317 PIPELINE graphics my_pipeline
3318   BIND BUFFER my_buf AS uniform_dynamic DESCRIPTOR_SET 1 BINDING 2
3319 END
3320 )";
3321 
3322   Parser parser;
3323   Result r = parser.Parse(in);
3324   ASSERT_FALSE(r.IsSuccess());
3325   EXPECT_EQ("5: expecting an OFFSET for dynamic buffer type", r.Error());
3326 }
3327 
TEST_F(AmberScriptParserTest,BindUniformBufferDynamicEmptyOffset)3328 TEST_F(AmberScriptParserTest, BindUniformBufferDynamicEmptyOffset) {
3329   std::string in = R"(
3330 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
3331 PIPELINE graphics my_pipeline
3332   BIND BUFFER my_buf AS uniform_dynamic DESCRIPTOR_SET 1 BINDING 2 OFFSET
3333 END
3334 )";
3335 
3336   Parser parser;
3337   Result r = parser.Parse(in);
3338   ASSERT_FALSE(r.IsSuccess());
3339   EXPECT_EQ("5: expecting an integer value for OFFSET", r.Error());
3340 }
3341 
TEST_F(AmberScriptParserTest,BindUniformBufferDynamicInvalidOffset)3342 TEST_F(AmberScriptParserTest, BindUniformBufferDynamicInvalidOffset) {
3343   std::string in = R"(
3344 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
3345 PIPELINE graphics my_pipeline
3346   BIND BUFFER my_buf AS uniform_dynamic DESCRIPTOR_SET 1 BINDING 2 OFFSET foo
3347 END
3348 )";
3349 
3350   Parser parser;
3351   Result r = parser.Parse(in);
3352   ASSERT_FALSE(r.IsSuccess());
3353   EXPECT_EQ("4: expecting an integer value for OFFSET", r.Error());
3354 }
3355 
TEST_F(AmberScriptParserTest,BindUniformBufferArrayDynamicNotEnoughOffsets)3356 TEST_F(AmberScriptParserTest, BindUniformBufferArrayDynamicNotEnoughOffsets) {
3357   std::string in = R"(
3358 BUFFER buf0 FORMAT R32G32B32A32_SFLOAT
3359 BUFFER buf1 FORMAT R32G32B32A32_SFLOAT
3360 
3361 PIPELINE graphics my_pipeline
3362   BIND BUFFER_ARRAY buf0 buf1 AS uniform_dynamic DESCRIPTOR_SET 1 BINDING 2 OFFSET 8
3363 END
3364 )";
3365 
3366   Parser parser;
3367   Result r = parser.Parse(in);
3368   ASSERT_FALSE(r.IsSuccess());
3369   EXPECT_EQ("7: expecting an OFFSET value for each buffer in the array",
3370             r.Error());
3371 }
3372 
TEST_F(AmberScriptParserTest,BindStorageBufferDynamic)3373 TEST_F(AmberScriptParserTest, BindStorageBufferDynamic) {
3374   std::string in = R"(
3375 SHADER vertex my_shader PASSTHROUGH
3376 SHADER fragment my_fragment GLSL
3377 # GLSL Shader
3378 END
3379 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
3380 
3381 PIPELINE graphics my_pipeline
3382   ATTACH my_shader
3383   ATTACH my_fragment
3384 
3385   BIND BUFFER my_buf AS storage_dynamic DESCRIPTOR_SET 1 BINDING 2 OFFSET 8
3386 END
3387 )";
3388 
3389   Parser parser;
3390   Result r = parser.Parse(in);
3391   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3392 
3393   auto script = parser.GetScript();
3394   const auto& pipelines = script->GetPipelines();
3395   ASSERT_EQ(1U, pipelines.size());
3396 
3397   const auto* pipeline = pipelines[0].get();
3398   const auto& bufs = pipeline->GetBuffers();
3399   ASSERT_EQ(1U, bufs.size());
3400   EXPECT_EQ(BufferType::kStorageDynamic, bufs[0].type);
3401   EXPECT_EQ(1U, bufs[0].descriptor_set);
3402   EXPECT_EQ(2U, bufs[0].binding);
3403   EXPECT_EQ(8u, bufs[0].dynamic_offset);
3404   EXPECT_EQ(static_cast<uint32_t>(0), bufs[0].location);
3405   EXPECT_EQ(FormatType::kR32G32B32A32_SFLOAT,
3406             bufs[0].buffer->GetFormat()->GetFormatType());
3407 }
3408 
TEST_F(AmberScriptParserTest,BindStorageBufferArrayDynamic)3409 TEST_F(AmberScriptParserTest, BindStorageBufferArrayDynamic) {
3410   std::string in = R"(
3411 SHADER vertex my_shader PASSTHROUGH
3412 SHADER fragment my_fragment GLSL
3413 # GLSL Shader
3414 END
3415 BUFFER buf0 FORMAT R32G32B32A32_SFLOAT
3416 BUFFER buf1 FORMAT R32G32B32A32_SFLOAT
3417 
3418 PIPELINE graphics my_pipeline
3419   ATTACH my_shader
3420   ATTACH my_fragment
3421 
3422   BIND BUFFER_ARRAY buf0 buf1 AS storage_dynamic DESCRIPTOR_SET 1 BINDING 2 OFFSET 8 16
3423 END
3424 )";
3425 
3426   Parser parser;
3427   Result r = parser.Parse(in);
3428   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3429 
3430   auto script = parser.GetScript();
3431   const auto& pipelines = script->GetPipelines();
3432   ASSERT_EQ(1U, pipelines.size());
3433 
3434   const auto* pipeline = pipelines[0].get();
3435   const auto& bufs = pipeline->GetBuffers();
3436   ASSERT_EQ(2U, bufs.size());
3437   EXPECT_EQ(BufferType::kStorageDynamic, bufs[0].type);
3438   EXPECT_EQ(1U, bufs[0].descriptor_set);
3439   EXPECT_EQ(2U, bufs[0].binding);
3440   EXPECT_EQ(8u, bufs[0].dynamic_offset);
3441   EXPECT_EQ(static_cast<uint32_t>(0), bufs[0].location);
3442   EXPECT_EQ(FormatType::kR32G32B32A32_SFLOAT,
3443             bufs[0].buffer->GetFormat()->GetFormatType());
3444   EXPECT_EQ(1U, bufs[1].descriptor_set);
3445   EXPECT_EQ(2U, bufs[1].binding);
3446   EXPECT_EQ(16u, bufs[1].dynamic_offset);
3447   EXPECT_EQ(static_cast<uint32_t>(0), bufs[1].location);
3448   EXPECT_EQ(FormatType::kR32G32B32A32_SFLOAT,
3449             bufs[1].buffer->GetFormat()->GetFormatType());
3450 }
3451 
TEST_F(AmberScriptParserTest,BindStorageBufferDynamicMissingOffset)3452 TEST_F(AmberScriptParserTest, BindStorageBufferDynamicMissingOffset) {
3453   std::string in = R"(
3454 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
3455 PIPELINE graphics my_pipeline
3456   BIND BUFFER my_buf AS storage_dynamic DESCRIPTOR_SET 1 BINDING 2
3457 END
3458 )";
3459 
3460   Parser parser;
3461   Result r = parser.Parse(in);
3462   ASSERT_FALSE(r.IsSuccess());
3463   EXPECT_EQ("5: expecting an OFFSET for dynamic buffer type", r.Error());
3464 }
3465 
TEST_F(AmberScriptParserTest,BindStorageBufferDynamicEmptyOffset)3466 TEST_F(AmberScriptParserTest, BindStorageBufferDynamicEmptyOffset) {
3467   std::string in = R"(
3468 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
3469 PIPELINE graphics my_pipeline
3470   BIND BUFFER my_buf AS storage_dynamic DESCRIPTOR_SET 1 BINDING 2 OFFSET
3471 END
3472 )";
3473 
3474   Parser parser;
3475   Result r = parser.Parse(in);
3476   ASSERT_FALSE(r.IsSuccess());
3477   EXPECT_EQ("5: expecting an integer value for OFFSET", r.Error());
3478 }
3479 
TEST_F(AmberScriptParserTest,BindStorageBufferDynamicInvalidOffset)3480 TEST_F(AmberScriptParserTest, BindStorageBufferDynamicInvalidOffset) {
3481   std::string in = R"(
3482 BUFFER my_buf FORMAT R32G32B32A32_SFLOAT
3483 PIPELINE graphics my_pipeline
3484   BIND BUFFER my_buf AS storage_dynamic DESCRIPTOR_SET 1 BINDING 2 OFFSET foo
3485 END
3486 )";
3487 
3488   Parser parser;
3489   Result r = parser.Parse(in);
3490   ASSERT_FALSE(r.IsSuccess());
3491   EXPECT_EQ("4: expecting an integer value for OFFSET", r.Error());
3492 }
3493 
TEST_F(AmberScriptParserTest,BindStorageBufferArrayDynamicNotEnoughOffsets)3494 TEST_F(AmberScriptParserTest, BindStorageBufferArrayDynamicNotEnoughOffsets) {
3495   std::string in = R"(
3496 BUFFER buf0 FORMAT R32G32B32A32_SFLOAT
3497 BUFFER buf1 FORMAT R32G32B32A32_SFLOAT
3498 
3499 PIPELINE graphics my_pipeline
3500   BIND BUFFER_ARRAY buf0 buf1 AS storage_dynamic DESCRIPTOR_SET 1 BINDING 2 OFFSET 8
3501 END
3502 )";
3503 
3504   Parser parser;
3505   Result r = parser.Parse(in);
3506   ASSERT_FALSE(r.IsSuccess());
3507   EXPECT_EQ("7: expecting an OFFSET value for each buffer in the array",
3508             r.Error());
3509 }
3510 
TEST_F(AmberScriptParserTest,BindResolveTarget)3511 TEST_F(AmberScriptParserTest, BindResolveTarget) {
3512   std::string in = R"(
3513 SHADER vertex my_shader PASSTHROUGH
3514 SHADER fragment my_fragment GLSL
3515 # GLSL Shader
3516 END
3517 IMAGE my_fb_ms DIM_2D WIDTH 64 HEIGHT 64 FORMAT R32G32B32A32_SFLOAT SAMPLES 4
3518 IMAGE my_fb DIM_2D WIDTH 64 HEIGHT 64 FORMAT R32G32B32A32_SFLOAT
3519 
3520 PIPELINE graphics my_pipeline
3521   ATTACH my_shader
3522   ATTACH my_fragment
3523 
3524   FRAMEBUFFER_SIZE 64 64
3525   BIND BUFFER my_fb_ms AS color LOCATION 0
3526   BIND BUFFER my_fb AS resolve
3527 END)";
3528 
3529   Parser parser;
3530   Result r = parser.Parse(in);
3531   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3532 
3533   auto script = parser.GetScript();
3534   const auto& pipelines = script->GetPipelines();
3535   ASSERT_EQ(1U, pipelines.size());
3536 
3537   const auto* pipeline = pipelines[0].get();
3538   const auto& resolve_targets = pipeline->GetResolveTargets();
3539   ASSERT_EQ(1U, resolve_targets.size());
3540 
3541   const auto& buf_info = resolve_targets[0];
3542   ASSERT_TRUE(buf_info.buffer != nullptr);
3543   EXPECT_EQ(64u * 64u, buf_info.buffer->ElementCount());
3544   EXPECT_EQ(64u * 64u * 4u, buf_info.buffer->ValueCount());
3545   EXPECT_EQ(64u * 64u * 4u * sizeof(float), buf_info.buffer->GetSizeInBytes());
3546 }
3547 
TEST_F(AmberScriptParserTest,BindResolveTargetMissingBuffer)3548 TEST_F(AmberScriptParserTest, BindResolveTargetMissingBuffer) {
3549   std::string in = R"(
3550 SHADER vertex my_shader PASSTHROUGH
3551 SHADER fragment my_fragment GLSL
3552 # GLSL Shader
3553 END
3554 BUFFER my_fb FORMAT R32G32B32A32_SFLOAT
3555 
3556 PIPELINE graphics my_pipeline
3557   ATTACH my_shader
3558   ATTACH my_fragment
3559 
3560   BIND BUFFER AS resolve
3561 END)";
3562 
3563   Parser parser;
3564   Result r = parser.Parse(in);
3565   ASSERT_FALSE(r.IsSuccess());
3566   EXPECT_EQ("12: unknown buffer: AS", r.Error());
3567 }
3568 
TEST_F(AmberScriptParserTest,BindResolveTargetNonDeclaredBuffer)3569 TEST_F(AmberScriptParserTest, BindResolveTargetNonDeclaredBuffer) {
3570   std::string in = R"(
3571 SHADER vertex my_shader PASSTHROUGH
3572 SHADER fragment my_fragment GLSL
3573 # GLSL Shader
3574 END
3575 IMAGE my_fb_ms DIM_2D WIDTH 64 HEIGHT 64 FORMAT R32G32B32A32_SFLOAT SAMPLES 4
3576 
3577 PIPELINE graphics my_pipeline
3578 ATTACH my_shader
3579 ATTACH my_fragment
3580 
3581 FRAMEBUFFER_SIZE 64 64
3582 BIND BUFFER my_fb_ms AS color LOCATION 0
3583 BIND BUFFER my_fb AS resolve
3584 END)";
3585   Parser parser;
3586   Result r = parser.Parse(in);
3587   ASSERT_FALSE(r.IsSuccess());
3588   EXPECT_EQ("14: unknown buffer: my_fb", r.Error());
3589 }
3590 
TEST_F(AmberScriptParserTest,BindMultipleResolveTargets)3591 TEST_F(AmberScriptParserTest, BindMultipleResolveTargets) {
3592   std::string in = R"(
3593 SHADER vertex my_shader PASSTHROUGH
3594 SHADER fragment my_fragment GLSL
3595 # GLSL Shader
3596 END
3597 IMAGE my_fb_ms0 DIM_2D WIDTH 64 HEIGHT 64 FORMAT R32G32B32A32_SFLOAT SAMPLES 4
3598 IMAGE my_fb_ms1 DIM_2D WIDTH 64 HEIGHT 64 FORMAT R32G32B32A32_SFLOAT SAMPLES 4
3599 IMAGE my_fb_ms2 DIM_2D WIDTH 64 HEIGHT 64 FORMAT R32G32B32A32_SFLOAT SAMPLES 4
3600 IMAGE my_fb0 DIM_2D WIDTH 64 HEIGHT 64 FORMAT R32G32B32A32_SFLOAT
3601 IMAGE my_fb1 DIM_2D WIDTH 64 HEIGHT 64 FORMAT R32G32B32A32_SFLOAT
3602 IMAGE my_fb2 DIM_2D WIDTH 64 HEIGHT 64 FORMAT R32G32B32A32_SFLOAT
3603 
3604 PIPELINE graphics my_pipeline
3605   ATTACH my_shader
3606   ATTACH my_fragment
3607 
3608   FRAMEBUFFER_SIZE 64 64
3609   BIND BUFFER my_fb_ms0 AS color LOCATION 0
3610   BIND BUFFER my_fb_ms1 AS color LOCATION 1
3611   BIND BUFFER my_fb_ms2 AS color LOCATION 2
3612   BIND BUFFER my_fb0 AS resolve
3613   BIND BUFFER my_fb1 AS resolve
3614   BIND BUFFER my_fb2 AS resolve
3615 END)";
3616 
3617   Parser parser;
3618   Result r = parser.Parse(in);
3619   ASSERT_TRUE(r.IsSuccess()) << r.Error();
3620 
3621   auto script = parser.GetScript();
3622   const auto& pipelines = script->GetPipelines();
3623   ASSERT_EQ(1U, pipelines.size());
3624 
3625   const auto* pipeline = pipelines[0].get();
3626   const auto& resolve_targets = pipeline->GetResolveTargets();
3627   ASSERT_EQ(3U, resolve_targets.size());
3628 
3629   for (const auto& buf_info : resolve_targets) {
3630     ASSERT_TRUE(buf_info.buffer != nullptr);
3631     EXPECT_EQ(64u * 64u, buf_info.buffer->ElementCount());
3632     EXPECT_EQ(64u * 64u * 4u, buf_info.buffer->ValueCount());
3633     EXPECT_EQ(64u * 64u * 4u * sizeof(float),
3634               buf_info.buffer->GetSizeInBytes());
3635   }
3636 }
3637 
3638 }  // namespace amberscript
3639 }  // namespace amber
3640