| // Copyright 2019 The Amber Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or parseried. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "gtest/gtest.h" |
| #include "src/amberscript/parser.h" |
| |
| namespace amber { |
| namespace amberscript { |
| |
| using AmberScriptParserTest = testing::Test; |
| |
| class DummyDelegate : public amber::Delegate { |
| public: |
| DummyDelegate() = default; |
| ~DummyDelegate() override = default; |
| |
| void Log(const std::string&) override {} |
| bool LogGraphicsCalls() const override { return false; } |
| void SetLogGraphicsCalls(bool) {} |
| bool LogExecuteCalls() const override { return false; } |
| void SetLogExecuteCalls(bool) {} |
| bool LogGraphicsCallsTime() const override { return false; } |
| void SetLogGraphicsCallsTime(bool) {} |
| uint64_t GetTimestampNs() const override { return 0; } |
| void SetScriptPath(std::string) {} |
| |
| amber::Result LoadBufferData(const std::string, |
| amber::BufferDataFileType type, |
| amber::BufferInfo* buffer) const override { |
| amber::Value v; |
| v.SetIntValue(static_cast<uint64_t>(type)); |
| buffer->values.push_back(v); |
| buffer->width = 1; |
| buffer->height = 1; |
| |
| return {}; |
| } |
| }; |
| |
| TEST_F(AmberScriptParserTest, BufferData) { |
| std::string in = R"( |
| BUFFER my_buffer DATA_TYPE uint32 DATA |
| 1 2 3 4 |
| 55 99 1234 |
| END)"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()) << r.Error(); |
| |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| |
| ASSERT_TRUE(buffers[0] != nullptr); |
| EXPECT_EQ("my_buffer", buffers[0]->GetName()); |
| |
| auto* buffer = buffers[0].get(); |
| EXPECT_TRUE(buffer->GetFormat()->IsUint32()); |
| EXPECT_EQ(Format::Layout::kStd430, buffer->GetFormat()->GetLayout()); |
| EXPECT_EQ(7U, buffer->ElementCount()); |
| EXPECT_EQ(7U, buffer->ValueCount()); |
| EXPECT_EQ(7U * sizeof(uint32_t), buffer->GetSizeInBytes()); |
| |
| std::vector<uint32_t> results = {1, 2, 3, 4, 55, 99, 1234}; |
| const auto* data = buffer->GetValues<uint32_t>(); |
| ASSERT_EQ(results.size(), buffer->ValueCount()); |
| for (size_t i = 0; i < results.size(); ++i) { |
| EXPECT_EQ(results[i], data[i]); |
| } |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferDataStd140) { |
| std::string in = R"( |
| BUFFER my_buffer DATA_TYPE uint32 STD140 DATA |
| 1 2 3 4 |
| 55 99 1234 |
| END)"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()) << r.Error(); |
| |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| |
| ASSERT_TRUE(buffers[0] != nullptr); |
| EXPECT_EQ("my_buffer", buffers[0]->GetName()); |
| |
| auto* buffer = buffers[0].get(); |
| EXPECT_TRUE(buffer->GetFormat()->IsUint32()); |
| EXPECT_EQ(Format::Layout::kStd140, buffer->GetFormat()->GetLayout()); |
| EXPECT_EQ(7U, buffer->ElementCount()); |
| EXPECT_EQ(7U, buffer->ValueCount()); |
| EXPECT_EQ(7U * sizeof(uint32_t), buffer->GetSizeInBytes()); |
| |
| std::vector<uint32_t> results = {1, 2, 3, 4, 55, 99, 1234}; |
| const auto* data = buffer->GetValues<uint32_t>(); |
| ASSERT_EQ(results.size(), buffer->ValueCount()); |
| for (size_t i = 0; i < results.size(); ++i) { |
| EXPECT_EQ(results[i], data[i]); |
| } |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferDataMatrixStd430) { |
| std::string in = R"( |
| BUFFER my_buffer DATA_TYPE mat2x2<float> STD430 DATA |
| 1 2 |
| 3 4 |
| END)"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()) << r.Error(); |
| |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| |
| ASSERT_TRUE(buffers[0] != nullptr); |
| EXPECT_EQ("my_buffer", buffers[0]->GetName()); |
| |
| auto* buffer = buffers[0].get(); |
| EXPECT_TRUE(buffer->GetFormat()->IsFloat32()); |
| EXPECT_EQ(Format::Layout::kStd430, buffer->GetFormat()->GetLayout()); |
| EXPECT_EQ(1U, buffer->ElementCount()); |
| EXPECT_EQ(4U, buffer->ValueCount()); |
| EXPECT_EQ(4U * sizeof(float), buffer->GetSizeInBytes()); |
| |
| std::vector<float> results = {1.f, 2.f, 3.f, 4.f}; |
| const auto* data = buffer->GetValues<float>(); |
| ASSERT_EQ(results.size(), buffer->ValueCount()); |
| for (size_t i = 0; i < results.size(); ++i) { |
| EXPECT_FLOAT_EQ(results[i], data[i]); |
| } |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferDataMatrixStd140) { |
| std::string in = R"( |
| BUFFER my_buffer DATA_TYPE mat2x2<float> STD140 DATA |
| 1 2 |
| 3 4 |
| END)"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()) << r.Error(); |
| |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| |
| ASSERT_TRUE(buffers[0] != nullptr); |
| EXPECT_EQ("my_buffer", buffers[0]->GetName()); |
| |
| auto* buffer = buffers[0].get(); |
| EXPECT_TRUE(buffer->GetFormat()->IsFloat32()); |
| EXPECT_EQ(Format::Layout::kStd140, buffer->GetFormat()->GetLayout()); |
| EXPECT_EQ(1U, buffer->ElementCount()); |
| EXPECT_EQ(4U, buffer->ValueCount()); |
| EXPECT_EQ(8U * sizeof(float), buffer->GetSizeInBytes()); |
| |
| std::vector<float> results = {1.f, 2.f, 0.f, 0.f, 3.f, 4.f, 0.f, 0.f}; |
| const auto* data = buffer->GetValues<float>(); |
| for (size_t i = 0; i < results.size(); ++i) { |
| EXPECT_FLOAT_EQ(results[i], data[i]); |
| } |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferDataStd430) { |
| std::string in = R"( |
| BUFFER my_buffer DATA_TYPE uint32 STD430 DATA |
| 1 2 3 4 |
| 55 99 1234 |
| END)"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()) << r.Error(); |
| |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| |
| ASSERT_TRUE(buffers[0] != nullptr); |
| EXPECT_EQ("my_buffer", buffers[0]->GetName()); |
| |
| auto* buffer = buffers[0].get(); |
| EXPECT_TRUE(buffer->GetFormat()->IsUint32()); |
| EXPECT_EQ(Format::Layout::kStd430, buffer->GetFormat()->GetLayout()); |
| EXPECT_EQ(7U, buffer->ElementCount()); |
| EXPECT_EQ(7U, buffer->ValueCount()); |
| EXPECT_EQ(7U * sizeof(uint32_t), buffer->GetSizeInBytes()); |
| |
| std::vector<uint32_t> results = {1, 2, 3, 4, 55, 99, 1234}; |
| const auto* data = buffer->GetValues<uint32_t>(); |
| ASSERT_EQ(results.size(), buffer->ValueCount()); |
| for (size_t i = 0; i < results.size(); ++i) { |
| EXPECT_EQ(results[i], data[i]); |
| } |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferDataArrayStd140) { |
| std::string in = R"( |
| BUFFER my_buffer DATA_TYPE uint32[] STD140 DATA |
| 1 2 3 4 |
| 55 99 1234 |
| END)"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()) << r.Error(); |
| |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| |
| ASSERT_TRUE(buffers[0] != nullptr); |
| EXPECT_EQ("my_buffer", buffers[0]->GetName()); |
| |
| auto* buffer = buffers[0].get(); |
| EXPECT_TRUE(buffer->GetFormat()->IsUint32()); |
| EXPECT_EQ(Format::Layout::kStd140, buffer->GetFormat()->GetLayout()); |
| EXPECT_EQ(7U, buffer->ElementCount()); |
| EXPECT_EQ(28U * sizeof(uint32_t), buffer->GetSizeInBytes()); |
| |
| std::vector<uint32_t> results = {1, 0, 0, 0, 2, 0, 0, 0, 3, 0, |
| 0, 0, 4, 0, 0, 0, 55, 0, 0, 0, |
| 99, 0, 0, 0, 1234, 0, 0, 0}; |
| const auto* data = buffer->GetValues<uint32_t>(); |
| for (size_t i = 0; i < results.size(); ++i) { |
| EXPECT_EQ(results[i], data[i]); |
| } |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferDataArrayStd430) { |
| std::string in = R"( |
| BUFFER my_buffer DATA_TYPE uint32[] STD430 DATA |
| 1 2 3 4 |
| 55 99 1234 |
| END)"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()) << r.Error(); |
| |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| |
| ASSERT_TRUE(buffers[0] != nullptr); |
| EXPECT_EQ("my_buffer", buffers[0]->GetName()); |
| |
| auto* buffer = buffers[0].get(); |
| EXPECT_TRUE(buffer->GetFormat()->IsUint32()); |
| EXPECT_EQ(Format::Layout::kStd430, buffer->GetFormat()->GetLayout()); |
| EXPECT_EQ(7U, buffer->ElementCount()); |
| EXPECT_EQ(7U, buffer->ValueCount()); |
| EXPECT_EQ(7U * sizeof(uint32_t), buffer->GetSizeInBytes()); |
| |
| std::vector<uint32_t> results = {1, 2, 3, 4, 55, 99, 1234}; |
| const auto* data = buffer->GetValues<uint32_t>(); |
| ASSERT_EQ(results.size(), buffer->ValueCount()); |
| for (size_t i = 0; i < results.size(); ++i) { |
| EXPECT_EQ(results[i], data[i]); |
| } |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferDataOneLine) { |
| std::string in = "BUFFER my_buffer DATA_TYPE uint32 DATA 1 2 3 4 END"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()) << r.Error(); |
| |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| |
| ASSERT_TRUE(buffers[0] != nullptr); |
| EXPECT_EQ("my_buffer", buffers[0]->GetName()); |
| |
| auto* buffer = buffers[0].get(); |
| EXPECT_TRUE(buffer->GetFormat()->IsUint32()); |
| EXPECT_EQ(Format::Layout::kStd430, buffer->GetFormat()->GetLayout()); |
| EXPECT_EQ(4U, buffer->ElementCount()); |
| EXPECT_EQ(4U, buffer->ValueCount()); |
| EXPECT_EQ(4U * sizeof(uint32_t), buffer->GetSizeInBytes()); |
| |
| std::vector<uint32_t> results = {1, 2, 3, 4}; |
| const auto* data = buffer->GetValues<uint32_t>(); |
| ASSERT_EQ(results.size(), buffer->ValueCount()); |
| for (size_t i = 0; i < results.size(); ++i) { |
| EXPECT_EQ(results[i], data[i]); |
| } |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferDataFloat) { |
| std::string in = "BUFFER my_buffer DATA_TYPE float DATA 1 2 3 4 END"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()) << r.Error(); |
| |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| |
| ASSERT_TRUE(buffers[0] != nullptr); |
| EXPECT_EQ("my_buffer", buffers[0]->GetName()); |
| |
| auto* buffer = buffers[0].get(); |
| EXPECT_TRUE(buffer->GetFormat()->IsFloat32()); |
| EXPECT_EQ(Format::Layout::kStd430, buffer->GetFormat()->GetLayout()); |
| EXPECT_EQ(4U, buffer->ElementCount()); |
| EXPECT_EQ(4U, buffer->ValueCount()); |
| EXPECT_EQ(4U * sizeof(float), buffer->GetSizeInBytes()); |
| |
| std::vector<float> results = {1, 2, 3, 4}; |
| const auto* data = buffer->GetValues<float>(); |
| ASSERT_EQ(results.size(), buffer->ValueCount()); |
| for (size_t i = 0; i < results.size(); ++i) { |
| EXPECT_FLOAT_EQ(results[i], data[i]); |
| } |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferFill) { |
| std::string in = "BUFFER my_buffer DATA_TYPE uint8 SIZE 5 FILL 5"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()) << r.Error(); |
| |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| |
| ASSERT_TRUE(buffers[0] != nullptr); |
| |
| auto* buffer = buffers[0].get(); |
| EXPECT_EQ("my_buffer", buffer->GetName()); |
| EXPECT_TRUE(buffer->GetFormat()->IsUint8()); |
| EXPECT_EQ(Format::Layout::kStd430, buffer->GetFormat()->GetLayout()); |
| EXPECT_EQ(5U, buffer->ElementCount()); |
| EXPECT_EQ(5U, buffer->ValueCount()); |
| EXPECT_EQ(5U * sizeof(uint8_t), buffer->GetSizeInBytes()); |
| |
| std::vector<uint32_t> results = {5, 5, 5, 5, 5}; |
| const auto* data = buffer->GetValues<uint8_t>(); |
| ASSERT_EQ(results.size(), buffer->ValueCount()); |
| for (size_t i = 0; i < results.size(); ++i) { |
| EXPECT_EQ(results[i], data[i]); |
| } |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferFillFloat) { |
| std::string in = "BUFFER my_buffer DATA_TYPE float SIZE 5 FILL 5.2"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()) << r.Error(); |
| |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| |
| ASSERT_TRUE(buffers[0] != nullptr); |
| |
| auto* buffer = buffers[0].get(); |
| EXPECT_EQ("my_buffer", buffer->GetName()); |
| EXPECT_TRUE(buffer->GetFormat()->IsFloat32()); |
| EXPECT_EQ(Format::Layout::kStd430, buffer->GetFormat()->GetLayout()); |
| EXPECT_EQ(5U, buffer->ElementCount()); |
| EXPECT_EQ(5U, buffer->ValueCount()); |
| EXPECT_EQ(5U * sizeof(float), buffer->GetSizeInBytes()); |
| |
| std::vector<float> results = {5.2f, 5.2f, 5.2f, 5.2f, 5.2f}; |
| const auto* data = buffer->GetValues<float>(); |
| ASSERT_EQ(results.size(), buffer->ValueCount()); |
| for (size_t i = 0; i < results.size(); ++i) { |
| EXPECT_FLOAT_EQ(results[i], data[i]); |
| } |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferSeries) { |
| std::string in = |
| "BUFFER my_buffer DATA_TYPE uint8 SIZE 5 SERIES_FROM 2 INC_BY 1"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()) << r.Error(); |
| |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| |
| ASSERT_TRUE(buffers[0] != nullptr); |
| |
| auto* buffer = buffers[0].get(); |
| EXPECT_EQ("my_buffer", buffer->GetName()); |
| EXPECT_TRUE(buffer->GetFormat()->IsUint8()); |
| EXPECT_EQ(Format::Layout::kStd430, buffer->GetFormat()->GetLayout()); |
| EXPECT_EQ(5U, buffer->ElementCount()); |
| EXPECT_EQ(5U, buffer->ValueCount()); |
| EXPECT_EQ(5U * sizeof(uint8_t), buffer->GetSizeInBytes()); |
| |
| std::vector<uint8_t> results = {2, 3, 4, 5, 6}; |
| const auto* data = buffer->GetValues<uint8_t>(); |
| ASSERT_EQ(results.size(), buffer->ValueCount()); |
| for (size_t i = 0; i < results.size(); ++i) { |
| EXPECT_EQ(results[i], data[i]); |
| } |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferSeriesFloat) { |
| std::string in = |
| "BUFFER my_buffer DATA_TYPE float SIZE 5 SERIES_FROM 2.2 INC_BY " |
| "1.1"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()) << r.Error(); |
| |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| |
| ASSERT_TRUE(buffers[0] != nullptr); |
| |
| auto* buffer = buffers[0].get(); |
| EXPECT_EQ("my_buffer", buffer->GetName()); |
| EXPECT_TRUE(buffer->GetFormat()->IsFloat32()); |
| EXPECT_EQ(Format::Layout::kStd430, buffer->GetFormat()->GetLayout()); |
| EXPECT_EQ(5U, buffer->ElementCount()); |
| EXPECT_EQ(5U, buffer->ValueCount()); |
| EXPECT_EQ(5U * sizeof(float), buffer->GetSizeInBytes()); |
| |
| std::vector<float> results = {2.2f, 3.3f, 4.4f, 5.5f, 6.6f}; |
| const auto* data = buffer->GetValues<float>(); |
| ASSERT_EQ(results.size(), buffer->ValueCount()); |
| for (size_t i = 0; i < results.size(); ++i) { |
| EXPECT_FLOAT_EQ(results[i], data[i]); |
| } |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferMultipleBuffers) { |
| std::string in = R"( |
| BUFFER color_buffer DATA_TYPE uint8 SIZE 5 FILL 5 |
| BUFFER storage_buffer DATA_TYPE uint32 DATA |
| 1 2 3 4 |
| 55 99 1234 |
| END)"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()) << r.Error(); |
| |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(2U, buffers.size()); |
| |
| ASSERT_TRUE(buffers[0] != nullptr); |
| |
| auto* buffer = buffers[0].get(); |
| EXPECT_EQ("color_buffer", buffer->GetName()); |
| EXPECT_TRUE(buffer->GetFormat()->IsUint8()); |
| EXPECT_EQ(Format::Layout::kStd430, buffer->GetFormat()->GetLayout()); |
| EXPECT_EQ(5U, buffer->ElementCount()); |
| EXPECT_EQ(5U, buffer->ValueCount()); |
| EXPECT_EQ(5U * sizeof(uint8_t), buffer->GetSizeInBytes()); |
| |
| std::vector<uint32_t> results0 = {5, 5, 5, 5, 5}; |
| const auto* data0 = buffer->GetValues<uint8_t>(); |
| ASSERT_EQ(results0.size(), buffer->ValueCount()); |
| for (size_t i = 0; i < results0.size(); ++i) { |
| EXPECT_EQ(results0[i], data0[i]); |
| } |
| |
| ASSERT_TRUE(buffers[1] != nullptr); |
| |
| buffer = buffers[1].get(); |
| EXPECT_EQ("storage_buffer", buffer->GetName()); |
| EXPECT_TRUE(buffer->GetFormat()->IsUint32()); |
| EXPECT_EQ(Format::Layout::kStd430, buffer->GetFormat()->GetLayout()); |
| EXPECT_EQ(7U, buffer->ElementCount()); |
| EXPECT_EQ(7U, buffer->ValueCount()); |
| EXPECT_EQ(7U * sizeof(uint32_t), buffer->GetSizeInBytes()); |
| |
| std::vector<uint32_t> results1 = {1, 2, 3, 4, 55, 99, 1234}; |
| const auto* data1 = buffer->GetValues<uint32_t>(); |
| ASSERT_EQ(results1.size(), buffer->ValueCount()); |
| for (size_t i = 0; i < results1.size(); ++i) { |
| EXPECT_EQ(results1[i], data1[i]); |
| } |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferFillMultiRow) { |
| std::string in = R"( |
| BUFFER my_index_buffer DATA_TYPE vec2<int32> SIZE 5 FILL 2)"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()) << r.Error(); |
| |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| |
| ASSERT_TRUE(buffers[0] != nullptr); |
| |
| auto* buffer = buffers[0].get(); |
| EXPECT_EQ("my_index_buffer", buffer->GetName()); |
| EXPECT_TRUE(buffer->GetFormat()->IsInt32()); |
| EXPECT_EQ(Format::Layout::kStd430, buffer->GetFormat()->GetLayout()); |
| EXPECT_EQ(5U, buffer->ElementCount()); |
| EXPECT_EQ(10U, buffer->ValueCount()); |
| EXPECT_EQ(10U * sizeof(int32_t), buffer->GetSizeInBytes()); |
| |
| std::vector<int32_t> results0 = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; |
| const auto* data0 = buffer->GetValues<int32_t>(); |
| for (size_t i = 0; i < results0.size(); ++i) { |
| EXPECT_EQ(results0[i], data0[i]); |
| } |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferDataMultiRowStd430) { |
| std::string in = R"( |
| BUFFER my_index_buffer DATA_TYPE vec2<int32> DATA |
| 2 3 |
| 4 5 |
| 6 7 |
| 8 9 |
| END |
| )"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()) << r.Error(); |
| |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| |
| ASSERT_TRUE(buffers[0] != nullptr); |
| |
| auto* buffer = buffers[0].get(); |
| EXPECT_EQ("my_index_buffer", buffer->GetName()); |
| EXPECT_TRUE(buffer->GetFormat()->IsInt32()); |
| EXPECT_EQ(Format::Layout::kStd430, buffer->GetFormat()->GetLayout()); |
| EXPECT_EQ(4U, buffer->ElementCount()); |
| EXPECT_EQ(8U, buffer->ValueCount()); |
| EXPECT_EQ(8U * sizeof(int32_t), buffer->GetSizeInBytes()); |
| |
| std::vector<int32_t> results0 = {2, 3, 4, 5, 6, 7, 8, 9}; |
| const auto* data0 = buffer->GetValues<int32_t>(); |
| for (size_t i = 0; i < results0.size(); ++i) { |
| EXPECT_EQ(results0[i], data0[i]); |
| } |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferDataMultiRowStd140) { |
| std::string in = R"( |
| BUFFER my_index_buffer DATA_TYPE vec2<int32> STD140 DATA |
| 2 3 |
| 4 5 |
| 6 7 |
| 8 9 |
| END |
| )"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()) << r.Error(); |
| |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| |
| ASSERT_TRUE(buffers[0] != nullptr); |
| |
| auto* buffer = buffers[0].get(); |
| EXPECT_EQ("my_index_buffer", buffer->GetName()); |
| EXPECT_TRUE(buffer->GetFormat()->IsInt32()); |
| EXPECT_EQ(Format::Layout::kStd140, buffer->GetFormat()->GetLayout()); |
| EXPECT_EQ(4U, buffer->ElementCount()); |
| EXPECT_EQ(8U, buffer->ValueCount()); |
| EXPECT_EQ(8U * sizeof(int32_t), buffer->GetSizeInBytes()); |
| |
| std::vector<int32_t> results0 = {2, 3, 4, 5, 6, 7, 8, 9}; |
| const auto* data0 = buffer->GetValues<int32_t>(); |
| for (size_t i = 0; i < results0.size(); ++i) { |
| EXPECT_EQ(results0[i], data0[i]); |
| } |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferDataHex) { |
| std::string in = R"( |
| BUFFER my_index_buffer DATA_TYPE uint32 DATA |
| 0xff000000 |
| 0x00ff0000 |
| 0x0000ff00 |
| 0x000000ff |
| END |
| )"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()) << r.Error(); |
| |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| |
| ASSERT_TRUE(buffers[0] != nullptr); |
| |
| auto* buffer = buffers[0].get(); |
| EXPECT_EQ("my_index_buffer", buffer->GetName()); |
| EXPECT_TRUE(buffer->GetFormat()->IsUint32()); |
| EXPECT_EQ(Format::Layout::kStd430, buffer->GetFormat()->GetLayout()); |
| EXPECT_EQ(4U, buffer->ElementCount()); |
| EXPECT_EQ(4U, buffer->ValueCount()); |
| EXPECT_EQ(4U * sizeof(uint32_t), buffer->GetSizeInBytes()); |
| |
| std::vector<uint32_t> results0 = {4278190080, 16711680, 65280, 255}; |
| const auto* data0 = buffer->GetValues<uint32_t>(); |
| ASSERT_EQ(results0.size(), buffer->ValueCount()); |
| for (size_t i = 0; i < results0.size(); ++i) { |
| EXPECT_EQ(results0[i], data0[i]); |
| } |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferFormat) { |
| std::string in = "BUFFER my_buf FORMAT R32G32B32A32_SINT"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()) << r.Error(); |
| |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| |
| ASSERT_TRUE(buffers[0] != nullptr); |
| auto* buffer = buffers[0].get(); |
| EXPECT_EQ("my_buf", buffer->GetName()); |
| |
| auto fmt = buffer->GetFormat(); |
| EXPECT_EQ(FormatType::kR32G32B32A32_SINT, fmt->GetFormatType()); |
| auto& segs = fmt->GetSegments(); |
| ASSERT_EQ(4U, segs.size()); |
| |
| for (size_t i = 0; i < 4; ++i) { |
| EXPECT_EQ(segs[i].GetNumBits(), 32u); |
| EXPECT_EQ(segs[i].GetFormatMode(), FormatMode::kSInt); |
| EXPECT_EQ(segs[i].GetName(), static_cast<FormatComponentType>(i)); |
| } |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferSamples) { |
| std::string in = "BUFFER my_buf FORMAT R8G8B8A8_UNORM SAMPLES 2"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()) << r.Error(); |
| |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| |
| ASSERT_TRUE(buffers[0] != nullptr); |
| auto* buffer = buffers[0].get(); |
| EXPECT_EQ("my_buf", buffer->GetName()); |
| EXPECT_EQ(2u, buffer->GetSamples()); |
| } |
| |
| struct BufferParseError { |
| const char* in; |
| const char* err; |
| }; |
| using AmberScriptParserBufferParseErrorTest = |
| testing::TestWithParam<BufferParseError>; |
| TEST_P(AmberScriptParserBufferParseErrorTest, Test) { |
| auto test_data = GetParam(); |
| |
| Parser parser; |
| Result r = parser.Parse(test_data.in); |
| ASSERT_FALSE(r.IsSuccess()) << test_data.in; |
| EXPECT_EQ(std::string(test_data.err), r.Error()) << test_data.in; |
| } |
| |
| INSTANTIATE_TEST_SUITE_P( |
| AmberScriptParserBufferParseErrorTest, |
| AmberScriptParserBufferParseErrorTest, |
| testing::Values( |
| BufferParseError{"BUFFER my_buf FORMAT 123", |
| "1: BUFFER FORMAT must be an identifier"}, |
| BufferParseError{"BUFFER my_buf FORMAT A23A32", |
| "1: invalid BUFFER FORMAT"}, |
| BufferParseError{"BUFFER my_buf FORMAT", |
| "1: BUFFER FORMAT must be an identifier"}, |
| BufferParseError{"BUFFER my_buffer FORMAT R32G32B32A32_SFLOAT EXTRA", |
| "1: unknown token: EXTRA"}, |
| BufferParseError{"BUFFER 1234 DATA_TYPE uint8 SIZE 5 FILL 5", |
| "1: invalid BUFFER name provided"}, |
| BufferParseError{"BUFFER DATA_TYPE uint8 SIZE 5 FILL 5", |
| "1: missing BUFFER name"}, |
| |
| BufferParseError{"BUFFER my_buf 1234", |
| "1: invalid BUFFER command provided"}, |
| BufferParseError{"BUFFER my_buf INVALID", |
| "1: unknown BUFFER command provided: INVALID"}, |
| BufferParseError{"BUFFER my_buf DATA_TYPE uint8 SIZE INVALID FILL 5", |
| "1: BUFFER size invalid"}, |
| BufferParseError{"BUFFER my_buf DATA_TYPE uint8 SIZE FILL 5", |
| "1: BUFFER size invalid"}, |
| BufferParseError{"BUFFER my_buf DATA_TYPE uint8 SIZE 5 FILL", |
| "1: missing BUFFER fill value"}, |
| BufferParseError{"BUFFER my_buf DATA_TYPE uint8 SIZE 5 FILL INVALID", |
| "1: invalid BUFFER fill value"}, |
| BufferParseError{"BUFFER my_buf DATA_TYPE uint8 SIZE 5 INVALID 5", |
| "1: invalid BUFFER initializer provided"}, |
| BufferParseError{"BUFFER my_buf DATA_TYPE uint8 SIZE 5 FILL INVALID", |
| "1: invalid BUFFER fill value"}, |
| BufferParseError{"BUFFER my_buf DATA_TYPE uint8 SIZE 5 FILL", |
| "1: missing BUFFER fill value"}, |
| BufferParseError{ |
| "BUFFER my_buf DATA_TYPE uint8 SIZE 5 SERIES_FROM INC_BY 2", |
| "1: invalid BUFFER series_from value"}, |
| BufferParseError{"BUFFER my_buf DATA_TYPE uint8 SIZE 5 SERIES_FROM 2", |
| "1: missing BUFFER series_from inc_by"}, |
| BufferParseError{ |
| "BUFFER my_buf DATA_TYPE uint8 SIZE 5 SERIES_FROM 2 INC_BY", |
| "1: missing BUFFER series_from inc_by value"}, |
| BufferParseError{"BUFFER my_buf DATA_TYPE uint8 SIZE 5 " |
| "SERIES_FROM INVALID INC_BY 2", |
| "1: invalid BUFFER series_from value"}, |
| BufferParseError{"BUFFER my_buf DATA_TYPE uint8 SIZE 5 " |
| "SERIES_FROM 1 INC_BY INVALID", |
| "1: invalid BUFFER series_from inc_by value"}, |
| BufferParseError{"BUFFER my_buf DATA_TYPE uint8 SIZE 5 " |
| "SERIES_FROM 1 INVALID 2", |
| "1: BUFFER series_from invalid command"}, |
| BufferParseError{ |
| "BUFFER my_index_buffer DATA_TYPE int32 DATA\n1.234\nEND", |
| "2: invalid BUFFER data value: 1.234"}, |
| BufferParseError{ |
| "BUFFER my_index_buffer DATA_TYPE int32 DATA\nINVALID\nEND", |
| "2: invalid BUFFER data value: INVALID"}, |
| BufferParseError{ |
| "BUFFER my_index_buffer DATA_TYPE int32 DATA INVALID\n123\nEND", |
| "1: invalid BUFFER data value: INVALID"}, |
| BufferParseError{ |
| "BUFFER my_index_buffer DATA_TYPE int32 SIZE 256 FILL " |
| "5 INVALID\n123\nEND", |
| "1: extra parameters after BUFFER fill command: INVALID"}, |
| BufferParseError{ |
| "BUFFER my_buffer DATA_TYPE int32 SIZE 256 SERIES_FROM 2 " |
| "INC_BY 5 " |
| "INVALID", |
| "1: extra parameters after BUFFER series_from command: INVALID"}, |
| BufferParseError{"BUFFER my_buf DATA_TYPE int32 SIZE 5 FILL 5\nBUFFER " |
| "my_buf DATA_TYPE int16 SIZE 5 FILL 2", |
| // NOLINTNEXTLINE(whitespace/parens) |
| "2: duplicate buffer name provided"}, |
| BufferParseError{"BUFFER my_buf FORMAT R8G8B8A8_UNORM SAMPLES 9", |
| "1: invalid sample count: 9"}, |
| BufferParseError{"BUFFER my_buf FORMAT R8G8B8A8_UNORM SAMPLES foo", |
| "1: expected integer value for SAMPLES"})); |
| |
| struct BufferData { |
| const char* name; |
| FormatMode type; |
| size_t num_bits; |
| size_t row_count; |
| size_t column_count; |
| bool is_array; |
| }; |
| |
| using AmberScriptParserBufferDataTypeTest = testing::TestWithParam<BufferData>; |
| TEST_P(AmberScriptParserBufferDataTypeTest, BufferTypes) { |
| auto test_data = GetParam(); |
| |
| std::string in = std::string("BUFFER my_buf DATA_TYPE ") + test_data.name + |
| " SIZE 2 FILL 5"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()) << test_data.name << " :" << r.Error(); |
| |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| |
| ASSERT_TRUE(buffers[0] != nullptr); |
| |
| auto* buffer = buffers[0].get(); |
| auto fmt = buffer->GetFormat(); |
| EXPECT_EQ(test_data.row_count, fmt->GetType()->RowCount()); |
| EXPECT_EQ(test_data.column_count, fmt->GetType()->ColumnCount()); |
| |
| auto& seg = fmt->GetSegments()[0]; |
| EXPECT_EQ(test_data.type, seg.GetFormatMode()); |
| EXPECT_EQ(test_data.num_bits, seg.GetNumBits()); |
| EXPECT_EQ(test_data.is_array, fmt->GetType()->IsArray()); |
| } |
| INSTANTIATE_TEST_SUITE_P( |
| AmberScriptParserTestsDataType, |
| AmberScriptParserBufferDataTypeTest, |
| testing::Values( |
| BufferData{"int8", FormatMode::kSInt, 8, 1, 1, false}, |
| BufferData{"int16", FormatMode::kSInt, 16, 1, 1, false}, |
| BufferData{"int32", FormatMode::kSInt, 32, 1, 1, false}, |
| BufferData{"int64", FormatMode::kSInt, 64, 1, 1, false}, |
| BufferData{"uint8", FormatMode::kUInt, 8, 1, 1, false}, |
| BufferData{"uint16", FormatMode::kUInt, 16, 1, 1, false}, |
| BufferData{"uint32", FormatMode::kUInt, 32, 1, 1, false}, |
| BufferData{"uint64", FormatMode::kUInt, 64, 1, 1, false}, |
| BufferData{"float", FormatMode::kSFloat, 32, 1, 1, false}, |
| BufferData{"double", FormatMode::kSFloat, 64, 1, 1, false}, |
| BufferData{"vec2<int8>", FormatMode::kSInt, 8, 2, 1, false}, |
| BufferData{"vec3<float>", FormatMode::kSFloat, 32, 3, 1, false}, |
| BufferData{"vec4<uint32>", FormatMode::kUInt, 32, 4, 1, false}, |
| BufferData{"mat2x4<int32>", FormatMode::kSInt, 32, 4, 2, false}, |
| BufferData{"mat3x3<float>", FormatMode::kSFloat, 32, 3, 3, false}, |
| BufferData{"mat4x2<uint16>", FormatMode::kUInt, 16, 2, 4, false}, |
| BufferData{"B8G8R8_UNORM", FormatMode::kUNorm, 8, 3, 1, |
| false})); // NOLINT(whitespace/parens) |
| |
| INSTANTIATE_TEST_SUITE_P( |
| AmberScriptParserTestsDataType2, |
| AmberScriptParserBufferDataTypeTest, |
| testing::Values( |
| BufferData{"int8[]", FormatMode::kSInt, 8, 1, 1, true}, |
| BufferData{"int16[]", FormatMode::kSInt, 16, 1, 1, true}, |
| BufferData{"int32[]", FormatMode::kSInt, 32, 1, 1, true}, |
| BufferData{"int64[]", FormatMode::kSInt, 64, 1, 1, true}, |
| BufferData{"uint8[]", FormatMode::kUInt, 8, 1, 1, true}, |
| BufferData{"uint16[]", FormatMode::kUInt, 16, 1, 1, true}, |
| BufferData{"uint32[]", FormatMode::kUInt, 32, 1, 1, true}, |
| BufferData{"uint64[]", FormatMode::kUInt, 64, 1, 1, true}, |
| BufferData{"float[]", FormatMode::kSFloat, 32, 1, 1, true}, |
| BufferData{"double[]", FormatMode::kSFloat, 64, 1, 1, true}, |
| BufferData{"vec2<int8>[]", FormatMode::kSInt, 8, 2, 1, true}, |
| BufferData{"vec3<float>[]", FormatMode::kSFloat, 32, 3, 1, true}, |
| BufferData{"vec4<uint32>[]", FormatMode::kUInt, 32, 4, 1, true}, |
| BufferData{"mat2x4<int32>[]", FormatMode::kSInt, 32, 4, 2, true}, |
| BufferData{"mat3x3<float>[]", FormatMode::kSFloat, 32, 3, 3, true}, |
| BufferData{"mat4x2<uint16>[]", FormatMode::kUInt, 16, 2, 4, |
| true})); // NOLINT(whitespace/parens) |
| |
| struct NameData { |
| const char* name; |
| }; |
| |
| using AmberScriptParserBufferDataTypeInvalidTest = |
| testing::TestWithParam<NameData>; |
| TEST_P(AmberScriptParserBufferDataTypeInvalidTest, BufferTypes) { |
| auto test_data = GetParam(); |
| |
| std::string in = std::string("BUFFER my_buf DATA_TYPE ") + test_data.name + |
| " SIZE 4 FILL 5"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_FALSE(r.IsSuccess()) << test_data.name; |
| EXPECT_EQ( |
| std::string("1: invalid data type '") + test_data.name + "' provided", |
| r.Error()) |
| << test_data.name; |
| } |
| INSTANTIATE_TEST_SUITE_P( |
| AmberScriptParserBufferDataTypeInvalidTestSamples, |
| AmberScriptParserBufferDataTypeInvalidTest, |
| testing::Values(NameData{"int17"}, |
| NameData{"int["}, |
| NameData{"int]"}, |
| NameData{"B8G8R8_UNORM[]"}, |
| NameData{"uintt0"}, |
| NameData{"vec7<uint8>"}, |
| NameData{"vec27<uint8>"}, |
| NameData{"vec2<vec2<float>>"}, |
| NameData{"vec2<mat2x2<float>>"}, |
| NameData{"vec2float>"}, |
| NameData{"vec2<uint32"}, |
| NameData{"vec2<uint4>"}, |
| NameData{"vec2<>"}, |
| NameData{"vec2"}, |
| NameData{"mat1x1<double>"}, |
| NameData{"mat5x2<double>"}, |
| NameData{"mat2x5<double>"}, |
| NameData{"mat22x22<double>"}, |
| NameData{"matx5<double>"}, |
| NameData{"mat2<double>"}, |
| NameData{"mat2x<double>"}, |
| NameData{"mat2x2<vec4<float>>"}, |
| NameData{"mat2x2<mat3x3<double>>"}, |
| NameData{"mat2x2<unit7>"}, |
| NameData{"mat2x2"}, |
| NameData{"mat2x2<>"})); // NOLINT(whitespace/parens) |
| |
| TEST_F(AmberScriptParserTest, BufferWithStructStd140) { |
| std::string in = R"( |
| STRUCT s |
| uint32 d |
| uint32 e |
| END |
| |
| STRUCT my_data |
| float a |
| uint32 b |
| s c |
| END |
| |
| BUFFER my_buffer DATA_TYPE my_data STD140 DATA |
| 1 # a |
| 64 # b |
| 128 # c.d |
| 220 # c.e |
| END)"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()) << r.Error(); |
| |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| |
| ASSERT_TRUE(buffers[0] != nullptr); |
| EXPECT_EQ("my_buffer", buffers[0]->GetName()); |
| |
| auto* buffer = buffers[0].get(); |
| EXPECT_TRUE(buffer->GetFormat()->GetType()->IsStruct()); |
| EXPECT_EQ(Format::Layout::kStd140, buffer->GetFormat()->GetLayout()); |
| |
| EXPECT_EQ(1U, buffer->ElementCount()); |
| EXPECT_EQ(32U, buffer->GetSizeInBytes()); |
| |
| const auto* data = buffer->GetValues<uint8_t>(); |
| EXPECT_FLOAT_EQ(1.f, *reinterpret_cast<const float*>(data + 0)); |
| EXPECT_EQ(64u, |
| *reinterpret_cast<const uint32_t*>(data + 4 /* sizeof(float) */)); |
| EXPECT_EQ(128u, |
| *reinterpret_cast<const uint32_t*>(data + 16 /* 8 round -> 16 */)); |
| EXPECT_EQ(220u, *reinterpret_cast<const uint32_t*>( |
| data + 20 /* 8 round -> 16 + 4 */)); |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferWithStructStd430) { |
| std::string in = R"( |
| STRUCT s |
| uint32 d |
| uint32 e |
| END |
| |
| STRUCT my_data |
| float a |
| uint32 b |
| s c |
| END |
| |
| BUFFER my_buffer DATA_TYPE my_data STD430 DATA |
| 1 # a |
| 64 # b |
| 128 # c.d |
| 220 # c.e |
| END)"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()) << r.Error(); |
| |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| |
| ASSERT_TRUE(buffers[0] != nullptr); |
| EXPECT_EQ("my_buffer", buffers[0]->GetName()); |
| |
| auto* buffer = buffers[0].get(); |
| EXPECT_TRUE(buffer->GetFormat()->GetType()->IsStruct()); |
| EXPECT_EQ(Format::Layout::kStd430, buffer->GetFormat()->GetLayout()); |
| |
| EXPECT_EQ(1U, buffer->ElementCount()); |
| EXPECT_EQ(16U, buffer->GetSizeInBytes()); |
| |
| const auto* data = buffer->GetValues<uint8_t>(); |
| EXPECT_FLOAT_EQ(1.f, *reinterpret_cast<const float*>(data + 0)); |
| EXPECT_EQ(64u, *reinterpret_cast<const uint32_t*>(data + 4)); |
| EXPECT_EQ(128u, *reinterpret_cast<const uint32_t*>(data + 8)); |
| EXPECT_EQ(220u, *reinterpret_cast<const uint32_t*>(data + 12)); |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferWithStructAndPaddingStd430) { |
| std::string in = R"( |
| STRUCT s |
| uint32 d OFFSET 8 |
| uint32 e OFFSET 16 |
| END |
| |
| STRUCT my_data |
| float a OFFSET 8 |
| uint32 b OFFSET 16 |
| s c; |
| END |
| |
| BUFFER my_buffer DATA_TYPE my_data STD430 DATA |
| 1 # a |
| 64 # b |
| 128 # c.d |
| 220 # c.e |
| END)"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()) << r.Error(); |
| |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| |
| ASSERT_TRUE(buffers[0] != nullptr); |
| EXPECT_EQ("my_buffer", buffers[0]->GetName()); |
| |
| auto* buffer = buffers[0].get(); |
| EXPECT_TRUE(buffer->GetFormat()->GetType()->IsStruct()); |
| EXPECT_EQ(Format::Layout::kStd430, buffer->GetFormat()->GetLayout()); |
| |
| EXPECT_EQ(1U, buffer->ElementCount()); |
| EXPECT_EQ(40U, buffer->GetSizeInBytes()); |
| |
| const auto* data = buffer->GetValues<uint8_t>(); |
| EXPECT_FLOAT_EQ(1.f, *reinterpret_cast<const float*>(data + 8)); |
| EXPECT_EQ(64u, *reinterpret_cast<const uint32_t*>(data + 16)); |
| EXPECT_EQ(128u, *reinterpret_cast<const uint32_t*>(data + 28)); |
| EXPECT_EQ(220u, *reinterpret_cast<const uint32_t*>(data + 36)); |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferWithStructPartialInitialization) { |
| std::string in = R"( |
| STRUCT my_data |
| uint32 a |
| float b |
| uint32 c |
| uint32 d |
| END |
| |
| BUFFER my_buffer DATA_TYPE my_data STD430 DATA |
| 1 # a |
| 64 # b |
| END)"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_FALSE(r.IsSuccess()); |
| EXPECT_EQ("12: Mismatched number of items in buffer", r.Error()); |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferWithStruct_vec_Std140) { |
| std::string in = R"( |
| |
| STRUCT my_data |
| float a |
| vec3<float> b |
| END |
| |
| BUFFER my_buffer DATA_TYPE my_data STD140 DATA |
| 1 # a |
| 64 128 220 # b |
| END)"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()) << r.Error(); |
| |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| |
| ASSERT_TRUE(buffers[0] != nullptr); |
| EXPECT_EQ("my_buffer", buffers[0]->GetName()); |
| |
| auto* buffer = buffers[0].get(); |
| EXPECT_TRUE(buffer->GetFormat()->GetType()->IsStruct()); |
| EXPECT_EQ(Format::Layout::kStd140, buffer->GetFormat()->GetLayout()); |
| |
| EXPECT_EQ(1U, buffer->ElementCount()); |
| EXPECT_EQ(32U, buffer->GetSizeInBytes()); |
| |
| const auto* data = buffer->GetValues<uint8_t>(); |
| EXPECT_FLOAT_EQ(1.f, *reinterpret_cast<const float*>(data + 0)); |
| EXPECT_FLOAT_EQ(64u, *reinterpret_cast<const float*>(data + 16)); |
| EXPECT_FLOAT_EQ(128u, *reinterpret_cast<const float*>(data + 20)); |
| EXPECT_FLOAT_EQ(220u, *reinterpret_cast<const float*>(data + 24)); |
| } |
| |
| TEST_F(AmberScriptParserTest, InvalidBufferWidth) { |
| std::string in = R"( |
| BUFFER buf DATA_TYPE vec4<float> WIDTH a |
| )"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_FALSE(r.IsSuccess()); |
| EXPECT_EQ("2: expected an integer for WIDTH", r.Error()); |
| } |
| |
| TEST_F(AmberScriptParserTest, ZeroBufferWidth) { |
| std::string in = R"( |
| BUFFER buf DATA_TYPE vec4<float> WIDTH 0 |
| )"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_FALSE(r.IsSuccess()); |
| EXPECT_EQ("2: expected WIDTH to be positive", r.Error()); |
| } |
| |
| TEST_F(AmberScriptParserTest, MissingBufferHeight) { |
| std::string in = R"( |
| BUFFER buf DATA_TYPE vec4<float> WIDTH 1 |
| )"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_FALSE(r.IsSuccess()); |
| EXPECT_EQ("3: BUFFER HEIGHT missing", r.Error()); |
| } |
| |
| TEST_F(AmberScriptParserTest, InvalidBufferHeight) { |
| std::string in = R"( |
| BUFFER buf DATA_TYPE vec4<float> WIDTH 1 HEIGHT 1.0 |
| )"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_FALSE(r.IsSuccess()); |
| EXPECT_EQ("2: expected an integer for HEIGHT", r.Error()); |
| } |
| |
| TEST_F(AmberScriptParserTest, ZeroBufferHeight) { |
| std::string in = R"( |
| BUFFER buf DATA_TYPE vec4<float> WIDTH 1 HEIGHT 0 |
| )"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_FALSE(r.IsSuccess()); |
| |
| EXPECT_EQ("2: expected HEIGHT to be positive", r.Error()); |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferWidthAndHeight) { |
| std::string in = R"( |
| BUFFER buf DATA_TYPE vec4<float> WIDTH 2 HEIGHT 3 |
| )"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()); |
| |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| ASSERT_TRUE(buffers[0] != nullptr); |
| EXPECT_EQ("buf", buffers[0]->GetName()); |
| |
| auto* buffer = buffers[0].get(); |
| EXPECT_EQ(2u, buffer->GetWidth()); |
| EXPECT_EQ(3u, buffer->GetHeight()); |
| EXPECT_EQ(6u, buffer->ElementCount()); |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferMipLevels) { |
| std::string in = "BUFFER my_buffer FORMAT R8G8B8A8_UNORM MIP_LEVELS 3"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()) << r.Error(); |
| |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| |
| ASSERT_TRUE(buffers[0] != nullptr); |
| EXPECT_EQ("my_buffer", buffers[0]->GetName()); |
| |
| auto* buffer = buffers[0].get(); |
| EXPECT_EQ(3U, buffer->GetMipLevels()); |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferMissingMipLevels) { |
| std::string in = "BUFFER my_buffer FORMAT R8G8B8A8_UNORM MIP_LEVELS"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_FALSE(r.IsSuccess()); |
| |
| EXPECT_EQ("1: invalid value for MIP_LEVELS", r.Error()); |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferMissingDataFile) { |
| std::string in = "BUFFER my_buffer FORMAT R8G8B8A8_UNORM FILE"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_FALSE(r.IsSuccess()); |
| |
| EXPECT_EQ("1: invalid value for FILE", r.Error()); |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferMissingDataFilePng) { |
| std::string in = "BUFFER my_buffer FORMAT R8G8B8A8_UNORM FILE PNG"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_FALSE(r.IsSuccess()); |
| |
| EXPECT_EQ("1: missing file name for FILE", r.Error()); |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferDataFilePng) { |
| std::string in = "BUFFER my_buffer FORMAT R8G8B8A8_UNORM FILE PNG foo.png"; |
| |
| DummyDelegate delegate; |
| Parser parser(&delegate); |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()); |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| ASSERT_TRUE(buffers[0] != nullptr); |
| ASSERT_EQ(static_cast<uint8_t>(amber::BufferDataFileType::kPng), |
| buffers[0]->GetValues<uint8_t>()[0]); |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferMissingDataFileBinary) { |
| std::string in = "BUFFER my_buffer DATA_TYPE float SIZE 10 FILE BINARY"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_FALSE(r.IsSuccess()); |
| |
| EXPECT_EQ("1: missing file name for FILE", r.Error()); |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferDataFileBinary) { |
| std::string in = |
| "BUFFER my_buffer DATA_TYPE int32 SIZE 10 FILE BINARY data.bin"; |
| |
| DummyDelegate delegate; |
| Parser parser(&delegate); |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()); |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| ASSERT_TRUE(buffers[0] != nullptr); |
| ASSERT_EQ(static_cast<uint8_t>(amber::BufferDataFileType::kBinary), |
| buffers[0]->GetValues<uint8_t>()[0]); |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferMissingDataFileText) { |
| std::string in = "BUFFER my_buffer DATA_TYPE float SIZE 10 FILE TEXT"; |
| |
| Parser parser; |
| Result r = parser.Parse(in); |
| ASSERT_FALSE(r.IsSuccess()); |
| |
| EXPECT_EQ("1: missing file name for FILE", r.Error()); |
| } |
| |
| TEST_F(AmberScriptParserTest, BufferDataFileText) { |
| std::string in = |
| "BUFFER my_buffer DATA_TYPE int32 SIZE 10 FILE TEXT data.txt"; |
| |
| DummyDelegate delegate; |
| Parser parser(&delegate); |
| Result r = parser.Parse(in); |
| ASSERT_TRUE(r.IsSuccess()); |
| auto script = parser.GetScript(); |
| const auto& buffers = script->GetBuffers(); |
| ASSERT_EQ(1U, buffers.size()); |
| ASSERT_TRUE(buffers[0] != nullptr); |
| ASSERT_EQ(static_cast<uint8_t>(amber::BufferDataFileType::kText), |
| buffers[0]->GetValues<uint8_t>()[0]); |
| } |
| |
| } // namespace amberscript |
| } // namespace amber |