• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 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 "src/vkscript/parser.h"
16 
17 #include <vector>
18 
19 #include "gtest/gtest.h"
20 #include "src/format.h"
21 
22 namespace amber {
23 namespace vkscript {
24 
25 using VkScriptParserTest = testing::Test;
26 
TEST_F(VkScriptParserTest,RequireBlockNoArgumentFeatures)27 TEST_F(VkScriptParserTest, RequireBlockNoArgumentFeatures) {
28   struct {
29     const char* name;
30   } features[] = {{"robustBufferAccess"},
31                   {"fullDrawIndexUint32"},
32                   {"imageCubeArray"},
33                   {"independentBlend"},
34                   {"geometryShader"},
35                   {"tessellationShader"},
36                   {"sampleRateShading"},
37                   {"dualSrcBlend"},
38                   {"logicOp"},
39                   {"multiDrawIndirect"},
40                   {"drawIndirectFirstInstance"},
41                   {"depthClamp"},
42                   {"depthBiasClamp"},
43                   {"fillModeNonSolid"},
44                   {"depthBounds"},
45                   {"wideLines"},
46                   {"largePoints"},
47                   {"alphaToOne"},
48                   {"multiViewport"},
49                   {"samplerAnisotropy"},
50                   {"textureCompressionETC2"},
51                   {"textureCompressionASTC_LDR"},
52                   {"textureCompressionBC"},
53                   {"occlusionQueryPrecise"},
54                   {"pipelineStatisticsQuery"},
55                   {"vertexPipelineStoresAndAtomics"},
56                   {"fragmentStoresAndAtomics"},
57                   {"shaderTessellationAndGeometryPointSize"},
58                   {"shaderImageGatherExtended"},
59                   {"shaderStorageImageExtendedFormats"},
60                   {"shaderStorageImageMultisample"},
61                   {"shaderStorageImageReadWithoutFormat"},
62                   {"shaderStorageImageWriteWithoutFormat"},
63                   {"shaderUniformBufferArrayDynamicIndexing"},
64                   {"shaderSampledImageArrayDynamicIndexing"},
65                   {"shaderStorageBufferArrayDynamicIndexing"},
66                   {"shaderStorageImageArrayDynamicIndexing"},
67                   {"shaderClipDistance"},
68                   {"shaderCullDistance"},
69                   {"shaderFloat64"},
70                   {"shaderInt64"},
71                   {"shaderInt16"},
72                   {"shaderResourceResidency"},
73                   {"shaderResourceMinLod"},
74                   {"sparseBinding"},
75                   {"sparseResidencyBuffer"},
76                   {"sparseResidencyImage2D"},
77                   {"sparseResidencyImage3D"},
78                   {"sparseResidency2Samples"},
79                   {"sparseResidency4Samples"},
80                   {"sparseResidency8Samples"},
81                   {"sparseResidency16Samples"},
82                   {"sparseResidencyAliased"},
83                   {"variableMultisampleRate"},
84                   {"inheritedQueries"},
85                   {"VariablePointerFeatures.variablePointers"},
86                   {"VariablePointerFeatures.variablePointersStorageBuffer"}};
87 
88   for (const auto& feature : features) {
89     std::string in = std::string("[require]\n") + feature.name + "\n";
90 
91     Parser parser;
92     parser.SkipValidationForTest();
93     Result r = parser.Parse(in);
94     ASSERT_TRUE(r.IsSuccess()) << r.Error();
95 
96     auto script = parser.GetScript();
97     auto feats = script->GetRequiredFeatures();
98     ASSERT_EQ(1U, feats.size());
99     EXPECT_EQ(feature.name, feats[0]);
100   }
101 }
102 
TEST_F(VkScriptParserTest,RequireBlockExtensions)103 TEST_F(VkScriptParserTest, RequireBlockExtensions) {
104   std::string block = R"([require]
105 VK_KHR_storage_buffer_storage_class
106 VK_KHR_variable_pointers
107 VK_KHR_get_physical_device_properties2)";
108 
109   Parser parser;
110   parser.SkipValidationForTest();
111   Result r = parser.Parse(block);
112   ASSERT_TRUE(r.IsSuccess()) << r.Error();
113 
114   auto script = parser.GetScript();
115   auto device_exts = script->GetRequiredDeviceExtensions();
116   ASSERT_EQ(2U, device_exts.size());
117   EXPECT_EQ("VK_KHR_storage_buffer_storage_class", device_exts[0]);
118   EXPECT_EQ("VK_KHR_variable_pointers", device_exts[1]);
119 
120   auto inst_exts = script->GetRequiredInstanceExtensions();
121   ASSERT_EQ(1U, inst_exts.size());
122   EXPECT_EQ("VK_KHR_get_physical_device_properties2", inst_exts[0]);
123 }
124 
TEST_F(VkScriptParserTest,RequireBlockFramebuffer)125 TEST_F(VkScriptParserTest, RequireBlockFramebuffer) {
126   std::string block = "[require]\nframebuffer R32G32B32A32_SFLOAT";
127 
128   Parser parser;
129   parser.SkipValidationForTest();
130   Result r = parser.Parse(block);
131   ASSERT_TRUE(r.IsSuccess());
132 
133   auto script = parser.GetScript();
134   const auto& bufs = script->GetBuffers();
135   ASSERT_EQ(1U, bufs.size());
136   EXPECT_EQ(FormatType::kR32G32B32A32_SFLOAT,
137             bufs[0]->GetFormat()->GetFormatType());
138 }
139 
TEST_F(VkScriptParserTest,RequireBlockDepthStencil)140 TEST_F(VkScriptParserTest, RequireBlockDepthStencil) {
141   std::string block = "[require]\ndepthstencil D24_UNORM_S8_UINT";
142 
143   Parser parser;
144   parser.SkipValidationForTest();
145   Result r = parser.Parse(block);
146   ASSERT_TRUE(r.IsSuccess()) << r.Error();
147 
148   auto script = parser.GetScript();
149   const auto& bufs = script->GetBuffers();
150   ASSERT_EQ(2U, bufs.size());
151   EXPECT_EQ(FormatType::kD24_UNORM_S8_UINT,
152             bufs[1]->GetFormat()->GetFormatType());
153 }
154 
TEST_F(VkScriptParserTest,RequireFbSize)155 TEST_F(VkScriptParserTest, RequireFbSize) {
156   std::string block = "[require]\nfbsize 300 400";
157 
158   Parser parser;
159   parser.SkipValidationForTest();
160   Result r = parser.Parse(block);
161   ASSERT_TRUE(r.IsSuccess()) << r.Error();
162 
163   auto script = parser.GetScript();
164   const auto& pipelines = script->GetPipelines();
165   ASSERT_EQ(1U, pipelines.size());
166   EXPECT_EQ(300u, pipelines[0]->GetFramebufferWidth());
167   EXPECT_EQ(400u, pipelines[0]->GetFramebufferHeight());
168 }
169 
TEST_F(VkScriptParserTest,RequireFbSizeMissingSize)170 TEST_F(VkScriptParserTest, RequireFbSizeMissingSize) {
171   std::string block = "[require]\nfbsize";
172 
173   Parser parser;
174   Result r = parser.Parse(block);
175   ASSERT_FALSE(r.IsSuccess());
176   EXPECT_EQ("2: Missing width and height for fbsize command", r.Error());
177 }
178 
TEST_F(VkScriptParserTest,RequireFbSizeMissingValue)179 TEST_F(VkScriptParserTest, RequireFbSizeMissingValue) {
180   std::string block = "[require]\nfbsize 200";
181 
182   Parser parser;
183   Result r = parser.Parse(block);
184   ASSERT_FALSE(r.IsSuccess());
185   EXPECT_EQ("2: Missing height for fbsize command", r.Error());
186 }
187 
TEST_F(VkScriptParserTest,RequireFbSizeExtraParams)188 TEST_F(VkScriptParserTest, RequireFbSizeExtraParams) {
189   std::string block = "[require]\nfbsize 200 300 EXTRA";
190 
191   Parser parser;
192   Result r = parser.Parse(block);
193   ASSERT_FALSE(r.IsSuccess());
194   EXPECT_EQ("2: Failed to parse requirements block: invalid token: EXTRA",
195             r.Error());
196 }
197 
TEST_F(VkScriptParserTest,RequireFbSizeInvalidFirstParam)198 TEST_F(VkScriptParserTest, RequireFbSizeInvalidFirstParam) {
199   std::string block = "[require]\nfbsize INVALID 200";
200 
201   Parser parser;
202   Result r = parser.Parse(block);
203   ASSERT_FALSE(r.IsSuccess());
204   EXPECT_EQ("2: Invalid width for fbsize command", r.Error());
205 }
206 
TEST_F(VkScriptParserTest,RequireFbSizeInvalidSecondParam)207 TEST_F(VkScriptParserTest, RequireFbSizeInvalidSecondParam) {
208   std::string block = "[require]\nfbsize 200 INVALID";
209 
210   Parser parser;
211   Result r = parser.Parse(block);
212   ASSERT_FALSE(r.IsSuccess());
213   EXPECT_EQ("2: Invalid height for fbsize command", r.Error());
214 }
215 
TEST_F(VkScriptParserTest,RequireBlockMultipleLines)216 TEST_F(VkScriptParserTest, RequireBlockMultipleLines) {
217   std::string block = R"([require]
218 # Requirements block stuff.
219 depthstencil D24_UNORM_S8_UINT
220 sparseResidency4Samples
221 framebuffer R32G32B32A32_SFLOAT
222 # More comments
223 inheritedQueries # line comment
224 )";
225 
226   Parser parser;
227   parser.SkipValidationForTest();
228   Result r = parser.Parse(block);
229   ASSERT_TRUE(r.IsSuccess()) << r.Error();
230 
231   auto script = parser.GetScript();
232   const auto& bufs = script->GetBuffers();
233   ASSERT_EQ(2U, bufs.size());
234   EXPECT_EQ(FormatType::kR32G32B32A32_SFLOAT,
235             bufs[0]->GetFormat()->GetFormatType());
236 
237   EXPECT_EQ(FormatType::kD24_UNORM_S8_UINT,
238             bufs[1]->GetFormat()->GetFormatType());
239 
240   auto feats = script->GetRequiredFeatures();
241   EXPECT_EQ("sparseResidency4Samples", feats[0]);
242   EXPECT_EQ("inheritedQueries", feats[1]);
243 }
244 
TEST_F(VkScriptParserTest,IndicesBlock)245 TEST_F(VkScriptParserTest, IndicesBlock) {
246   std::string block = "[indices]\n1 2 3";
247 
248   Parser parser;
249   parser.SkipValidationForTest();
250   Result r = parser.Parse(block);
251   ASSERT_TRUE(r.IsSuccess()) << r.Error();
252 
253   auto script = parser.GetScript();
254   const auto& bufs = script->GetBuffers();
255   ASSERT_EQ(2U, bufs.size());
256 
257   EXPECT_TRUE(bufs[1]->GetFormat()->IsUint32());
258   EXPECT_EQ(3U, bufs[1]->ElementCount());
259   EXPECT_EQ(3U, bufs[1]->ValueCount());
260   EXPECT_EQ(3U * sizeof(uint32_t), bufs[1]->GetSizeInBytes());
261 
262   const auto* data = bufs[1]->GetValues<uint32_t>();
263   EXPECT_EQ(1u, data[0]);
264   EXPECT_EQ(2u, data[1]);
265   EXPECT_EQ(3u, data[2]);
266 }
267 
TEST_F(VkScriptParserTest,IndicesBlockMultipleLines)268 TEST_F(VkScriptParserTest, IndicesBlockMultipleLines) {
269   std::string block = R"([indices]
270 # comment line
271 1 2 3   4 5 6
272 # another comment
273 7 8 9  10 11 12
274 )";
275 
276   Parser parser;
277   parser.SkipValidationForTest();
278   Result r = parser.Parse(block);
279   ASSERT_TRUE(r.IsSuccess()) << r.Error();
280 
281   auto script = parser.GetScript();
282   const auto& bufs = script->GetBuffers();
283   ASSERT_EQ(2U, bufs.size());
284 
285   const auto* data = bufs[1]->GetValues<uint32_t>();
286   std::vector<uint16_t> results = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
287   ASSERT_EQ(results.size(), bufs[1]->ValueCount());
288   for (size_t i = 0; i < results.size(); ++i) {
289     EXPECT_EQ(results[i], data[i]);
290   }
291 }
292 
TEST_F(VkScriptParserTest,IndicesBlockBadValue)293 TEST_F(VkScriptParserTest, IndicesBlockBadValue) {
294   std::string block = "[indices]\n1 a 3";
295 
296   Parser parser;
297   Result r = parser.Parse(block);
298   ASSERT_FALSE(r.IsSuccess());
299   EXPECT_EQ("1: Invalid value in indices block: a", r.Error());
300 }
301 
TEST_F(VkScriptParserTest,IndicesBlockValueTooLarge)302 TEST_F(VkScriptParserTest, IndicesBlockValueTooLarge) {
303   std::string block = "[indices]\n100000000000 3";
304 
305   Parser parser;
306   Result r = parser.Parse(block);
307   ASSERT_FALSE(r.IsSuccess());
308   EXPECT_EQ("1: Value too large in indices block: 100000000000", r.Error());
309 }
310 
TEST_F(VkScriptParserTest,VertexDataEmpty)311 TEST_F(VkScriptParserTest, VertexDataEmpty) {
312   std::string block = "[vertex data]\n#comment\n";
313 
314   Parser parser;
315   parser.SkipValidationForTest();
316   Result r = parser.Parse(block);
317   ASSERT_TRUE(r.IsSuccess());
318 
319   auto script = parser.GetScript();
320   EXPECT_EQ(1U, script->GetBuffers().size());
321 }
322 
TEST_F(VkScriptParserTest,VertexDataHeaderFormatString)323 TEST_F(VkScriptParserTest, VertexDataHeaderFormatString) {
324   std::string block = "[vertex data]\n0/R32G32_SFLOAT 1/A8B8G8R8_UNORM_PACK32";
325 
326   Parser parser;
327   parser.SkipValidationForTest();
328   Result r = parser.Parse(block);
329   ASSERT_TRUE(r.IsSuccess()) << r.Error();
330 
331   auto script = parser.GetScript();
332   const auto& bufs = script->GetBuffers();
333   ASSERT_EQ(3U, bufs.size());
334 
335   ASSERT_EQ(1U, script->GetPipelines().size());
336   const auto* pipeline = script->GetPipelines()[0].get();
337 
338   ASSERT_EQ(2U, pipeline->GetVertexBuffers().size());
339   const auto& pipeline_buffers = pipeline->GetVertexBuffers();
340 
341   EXPECT_EQ(static_cast<uint8_t>(0U), pipeline_buffers[0].location);
342   EXPECT_EQ(FormatType::kR32G32_SFLOAT, bufs[1]->GetFormat()->GetFormatType());
343   EXPECT_EQ(static_cast<uint32_t>(0), bufs[1]->ElementCount());
344 
345   EXPECT_EQ(1U, pipeline_buffers[1].location);
346   EXPECT_EQ(FormatType::kA8B8G8R8_UNORM_PACK32,
347             bufs[2]->GetFormat()->GetFormatType());
348   EXPECT_EQ(static_cast<uint32_t>(0), bufs[2]->ElementCount());
349 }
350 
TEST_F(VkScriptParserTest,VertexDataHeaderGlslString)351 TEST_F(VkScriptParserTest, VertexDataHeaderGlslString) {
352   std::string block = "[vertex data]\n0/float/vec2 1/int/vec3";
353 
354   Parser parser;
355   parser.SkipValidationForTest();
356   Result r = parser.Parse(block);
357   ASSERT_TRUE(r.IsSuccess()) << r.Error();
358 
359   auto script = parser.GetScript();
360   const auto& bufs = script->GetBuffers();
361   ASSERT_EQ(3U, bufs.size());
362 
363   ASSERT_EQ(1U, script->GetPipelines().size());
364   const auto* pipeline = script->GetPipelines()[0].get();
365 
366   ASSERT_EQ(2U, pipeline->GetVertexBuffers().size());
367   const auto& pipeline_buffers = pipeline->GetVertexBuffers();
368 
369   EXPECT_EQ(static_cast<uint8_t>(0U), pipeline_buffers[0].location);
370 
371   EXPECT_EQ(FormatType::kR32G32_SFLOAT, bufs[1]->GetFormat()->GetFormatType());
372 
373   auto& segs1 = bufs[1]->GetFormat()->GetSegments();
374   ASSERT_EQ(2U, segs1.size());
375   EXPECT_EQ(FormatMode::kSFloat, segs1[0].GetFormatMode());
376   EXPECT_EQ(FormatMode::kSFloat, segs1[1].GetFormatMode());
377   EXPECT_EQ(static_cast<uint32_t>(0), bufs[1]->ElementCount());
378 
379   EXPECT_EQ(1U, pipeline_buffers[1].location);
380   EXPECT_EQ(FormatType::kR32G32B32_SINT, bufs[2]->GetFormat()->GetFormatType());
381 
382   auto& segs2 = bufs[2]->GetFormat()->GetSegments();
383   ASSERT_EQ(4u, segs2.size());
384   EXPECT_EQ(FormatMode::kSInt, segs2[0].GetFormatMode());
385   EXPECT_EQ(FormatMode::kSInt, segs2[1].GetFormatMode());
386   EXPECT_EQ(FormatMode::kSInt, segs2[2].GetFormatMode());
387   EXPECT_TRUE(segs2[3].IsPadding());
388   EXPECT_EQ(static_cast<uint32_t>(0), bufs[2]->ElementCount());
389 }
390 
TEST_F(VkScriptParserTest,TestBlock)391 TEST_F(VkScriptParserTest, TestBlock) {
392   std::string block = R"([test]
393 clear color 255 255 255 0
394 clear depth 10
395 clear stencil 2
396 clear)";
397 
398   Parser parser;
399   parser.SkipValidationForTest();
400   Result r = parser.Parse(block);
401   ASSERT_TRUE(r.IsSuccess()) << r.Error();
402 
403   auto script = parser.GetScript();
404   const auto& cmds = script->GetCommands();
405   ASSERT_EQ(4U, cmds.size());
406 
407   ASSERT_TRUE(cmds[0]->IsClearColor());
408   auto* color_cmd = cmds[0]->AsClearColor();
409   EXPECT_FLOAT_EQ(255.f, color_cmd->GetR());
410   EXPECT_FLOAT_EQ(255.f, color_cmd->GetG());
411   EXPECT_FLOAT_EQ(255.f, color_cmd->GetB());
412   EXPECT_FLOAT_EQ(0.0f, color_cmd->GetA());
413 
414   ASSERT_TRUE(cmds[1]->IsClearDepth());
415   EXPECT_EQ(10U, cmds[1]->AsClearDepth()->GetValue());
416 
417   ASSERT_TRUE(cmds[2]->IsClearStencil());
418   EXPECT_EQ(2U, cmds[2]->AsClearStencil()->GetValue());
419 
420   EXPECT_TRUE(cmds[3]->IsClear());
421 }
422 
TEST_F(VkScriptParserTest,VertexDataRows)423 TEST_F(VkScriptParserTest, VertexDataRows) {
424   std::string block = R"([vertex data]
425 # Vertex data
426 0/R32G32B32_SFLOAT  1/R8G8B8_UNORM
427 -1    -1 0.25       255 128 1  # ending comment
428 # Another Row
429 0.25  -1 0.25       255 128 255
430 )";
431 
432   Parser parser;
433   parser.SkipValidationForTest();
434   Result r = parser.Parse(block);
435   ASSERT_TRUE(r.IsSuccess()) << r.Error();
436 
437   auto script = parser.GetScript();
438   const auto& bufs = script->GetBuffers();
439   ASSERT_EQ(3U, bufs.size());
440 
441   std::vector<float> seg_0 = {-1.f, -1.f, 0.25f, 0, 0.25f, -1.f, 0.25f, 0};
442   const auto* values_0 = bufs[1]->GetValues<float>();
443   for (size_t i = 0; i < seg_0.size(); ++i) {
444     EXPECT_FLOAT_EQ(seg_0[i], values_0[i]);
445   }
446 
447   std::vector<uint8_t> seg_1 = {255, 128, 1, 0, 255, 128, 255, 0};
448   const auto* values_1 = bufs[2]->GetValues<uint8_t>();
449   for (size_t i = 0; i < seg_1.size(); ++i) {
450     EXPECT_EQ(seg_1[i], values_1[i]);
451   }
452 }
453 
TEST_F(VkScriptParserTest,VertexDataShortRow)454 TEST_F(VkScriptParserTest, VertexDataShortRow) {
455   std::string block = R"([vertex data]
456 0/R32G32B32_SFLOAT  1/R8G8B8_UNORM
457 -1    -1 0.25       255 0 0
458 0.25  -1 0.25       255 0
459 )";
460 
461   Parser parser;
462   Result r = parser.Parse(block);
463   ASSERT_FALSE(r.IsSuccess());
464   EXPECT_EQ("3: Too few cells in given vertex data row", r.Error());
465 }
466 
TEST_F(VkScriptParserTest,VertexDataIncorrectValue)467 TEST_F(VkScriptParserTest, VertexDataIncorrectValue) {
468   std::string block = R"([vertex data]
469 0/R32G32B32_SFLOAT  1/R8G8B8_UNORM
470 -1    -1 0.25       255 StringValue 0
471 0.25  -1 0.25       255 0 0
472 )";
473 
474   Parser parser;
475   Result r = parser.Parse(block);
476   ASSERT_FALSE(r.IsSuccess());
477   EXPECT_EQ("2: Invalid vertex data value: StringValue", r.Error());
478 }
479 
TEST_F(VkScriptParserTest,VertexDataRowsWithHex)480 TEST_F(VkScriptParserTest, VertexDataRowsWithHex) {
481   std::string block = R"([vertex data]
482 0/A8B8G8R8_UNORM_PACK32
483 0xff0000ff
484 0xffff0000
485 )";
486 
487   Parser parser;
488   parser.SkipValidationForTest();
489   Result r = parser.Parse(block);
490   ASSERT_TRUE(r.IsSuccess()) << r.Error();
491 
492   auto script = parser.GetScript();
493   const auto& bufs = script->GetBuffers();
494   ASSERT_EQ(2U, bufs.size());
495 
496   std::vector<uint32_t> seg_0 = {0xff0000ff, 0xffff0000};
497   const auto* values_0 = bufs[1]->GetValues<uint32_t>();
498   ASSERT_EQ(seg_0.size(), bufs[1]->ValueCount());
499 
500   for (size_t i = 0; i < seg_0.size(); ++i) {
501     EXPECT_EQ(seg_0[i], values_0[i]);
502   }
503 }
504 
TEST_F(VkScriptParserTest,VertexDataRowsWithHexWrongColumn)505 TEST_F(VkScriptParserTest, VertexDataRowsWithHexWrongColumn) {
506   std::string block = R"([vertex data]
507 0/R32G32B32_SFLOAT  1/R8G8B8_UNORM
508 -1    -1 0.25       0xffff0000
509 0.25  -1 0.25       255 0
510 )";
511 
512   Parser parser;
513   Result r = parser.Parse(block);
514   ASSERT_FALSE(r.IsSuccess());
515   EXPECT_EQ("2: Invalid vertex data value: 0xffff0000", r.Error());
516 }
517 
TEST_F(VkScriptParserTest,ErrorLineNumberBug195)518 TEST_F(VkScriptParserTest, ErrorLineNumberBug195) {
519   std::string input = R"([compute shader]
520 #version 430
521 
522 void main() {
523 }
524 
525 [test]
526 # Error must report "9: Unknown command: unknown"
527 unknown
528 })";
529 
530   Parser parser;
531   Result r = parser.Parse(input);
532   ASSERT_FALSE(r.IsSuccess());
533   EXPECT_EQ("9: Unknown command: unknown", r.Error());
534 }
535 
536 }  // namespace vkscript
537 }  // namespace amber
538