aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/amber_script.md7
-rw-r--r--include/amber/amber.h15
-rw-r--r--samples/amber.cc40
-rw-r--r--src/amberscript/parser.cc42
-rw-r--r--src/amberscript/parser_buffer_test.cc69
-rw-r--r--src/buffer.h12
-rw-r--r--src/executor.cc14
-rw-r--r--tests/cases/buffer_load_binary.amber55
-rw-r--r--tests/cases/draw_png_texture.amber2
-rw-r--r--tests/cases/vec4data.binbin0 -> 48 bytes
10 files changed, 235 insertions, 21 deletions
diff --git a/docs/amber_script.md b/docs/amber_script.md
index f1540f9..c935d5b 100644
--- a/docs/amber_script.md
+++ b/docs/amber_script.md
@@ -193,6 +193,11 @@ BUFFER {name} DATA_TYPE {type} {STD140 | STD430} SIZE _size_in_items_ \
BUFFER {name} DATA_TYPE {type} {STD140 | STD430} WIDTH {w} HEIGHT {h} \
{initializer}
+# Defines a buffer which is filled with binary data from a file specified
+# by `FILE`.
+BUFFER {name} DATA_TYPE {type} {STD140 | STD430} SIZE _size_in_items_ \
+ FILE BINARY {file_name}
+
# Creates a buffer which will store the given `FORMAT` of data. These
# buffers are used as image and depth buffers in the `PIPELINE` commands.
# The buffer will be sized based on the `RENDER_SIZE` of the `PIPELINE`.
@@ -202,7 +207,7 @@ BUFFER {name} FORMAT {format_string} \
# Load buffer data from a PNG image with file name specified by `FILE`.
# The file path is relative to the script file being run. Format specified
# by `FORMAT` must match the image format.
-BUFFER {name} FORMAT {format_string} FILE {file_name.png}
+BUFFER {name} FORMAT {format_string} FILE PNG {file_name.png}
```
#### Images
diff --git a/include/amber/amber.h b/include/amber/amber.h
index b665de2..ddf5779 100644
--- a/include/amber/amber.h
+++ b/include/amber/amber.h
@@ -50,7 +50,7 @@ struct EngineConfig {
virtual ~EngineConfig();
};
-/// Stores information for a biffer.
+/// Stores information for a buffer.
struct BufferInfo {
BufferInfo();
BufferInfo(const BufferInfo&);
@@ -70,6 +70,18 @@ struct BufferInfo {
std::vector<Value> values;
};
+/// Types of source file to load buffer data from.
+enum class BufferDataFileType : int8_t {
+ /// Unknown file type
+ kUnknown = -1,
+ /// A text file
+ kText = 0,
+ /// A binary file
+ kBinary,
+ /// A PNG file
+ kPng
+};
+
/// Delegate class for various hook functions
class Delegate {
public:
@@ -87,6 +99,7 @@ class Delegate {
virtual bool LogExecuteCalls() const = 0;
/// Loads buffer data from a file
virtual amber::Result LoadBufferData(const std::string file_name,
+ BufferDataFileType file_type,
amber::BufferInfo* buffer) const = 0;
};
diff --git a/samples/amber.cc b/samples/amber.cc
index 31e66f9..01ff159 100644
--- a/samples/amber.cc
+++ b/samples/amber.cc
@@ -254,7 +254,7 @@ bool ParseArgs(const std::vector<std::string>& args, Options* opts) {
return true;
}
-std::string ReadFile(const std::string& input_file) {
+std::vector<char> ReadFile(const std::string& input_file) {
FILE* file = nullptr;
#if defined(_MSC_VER)
fopen_s(&file, input_file.c_str(), "rb");
@@ -287,7 +287,7 @@ std::string ReadFile(const std::string& input_file) {
return {};
}
- return std::string(data.begin(), data.end());
+ return data;
}
class SampleDelegate : public amber::Delegate {
@@ -327,19 +327,36 @@ class SampleDelegate : public amber::Delegate {
void SetScriptPath(std::string path) { path_ = path; }
amber::Result LoadBufferData(const std::string file_name,
+ amber::BufferDataFileType file_type,
amber::BufferInfo* buffer) const override {
+ if (file_type == amber::BufferDataFileType::kPng) {
#if AMBER_ENABLE_LODEPNG
- // Try to load as png first.
- amber::Result r = png::LoadPNG(path_ + file_name, &buffer->width,
- &buffer->height, &buffer->values);
-
- if (r.IsSuccess())
- return r;
+ return png::LoadPNG(path_ + file_name, &buffer->width, &buffer->height,
+ &buffer->values);
+#else
+ return amber::Result("PNG support is not enabled in compile options.");
#endif // AMBER_ENABLE_LODEPNG
+ } else if (file_type == amber::BufferDataFileType::kBinary) {
+ auto data = ReadFile(path_ + file_name);
+ if (data.empty())
+ return amber::Result("Failed to load buffer data " + file_name);
+
+ for (auto d : data) {
+ amber::Value v;
+ v.SetIntValue(static_cast<uint64_t>(d));
+ buffer->values.push_back(v);
+ }
+
+ buffer->width = 1;
+ buffer->height = 1;
- // TODO(asuonpaa): Try to load a binary format.
+ } else {
+ assert(file_type == amber::BufferDataFileType::kText);
- return amber::Result("Failed to load buffer data " + file_name);
+ // TODO(asuonpaa): Read text file and pass it to parser.
+ }
+
+ return {};
}
private:
@@ -432,7 +449,8 @@ int main(int argc, const char** argv) {
};
std::vector<RecipeData> recipe_data;
for (const auto& file : options.input_filenames) {
- auto data = ReadFile(file);
+ auto char_data = ReadFile(file);
+ auto data = std::string(char_data.begin(), char_data.end());
if (data.empty()) {
std::cerr << file << " is empty." << std::endl;
failures.push_back(file);
diff --git a/src/amberscript/parser.cc b/src/amberscript/parser.cc
index 10162b8..bc18271 100644
--- a/src/amberscript/parser.cc
+++ b/src/amberscript/parser.cc
@@ -1265,7 +1265,22 @@ Result Parser::ParseBuffer() {
if (!token->IsIdentifier())
return Result("invalid value for FILE");
- buffer->SetDataFile(token->AsString());
+ BufferDataFileType file_type = BufferDataFileType::kPng;
+
+ if (token->AsString() == "TEXT") {
+ file_type = BufferDataFileType::kText;
+ token = tokenizer_->NextToken();
+ } else if (token->AsString() == "BINARY") {
+ file_type = BufferDataFileType::kBinary;
+ token = tokenizer_->NextToken();
+ } else if (token->AsString() == "PNG") {
+ token = tokenizer_->NextToken();
+ }
+
+ if (!token->IsIdentifier())
+ return Result("missing file name for FILE");
+
+ buffer->SetDataFile(token->AsString(), file_type);
} else {
break;
}
@@ -1516,6 +1531,31 @@ Result Parser::ParseBufferInitializerSize(Buffer* buffer) {
return ParseBufferInitializerFill(buffer, size_in_items);
if (token->AsString() == "SERIES_FROM")
return ParseBufferInitializerSeries(buffer, size_in_items);
+ if (token->AsString() == "FILE") {
+ token = tokenizer_->NextToken();
+
+ if (!token->IsIdentifier())
+ return Result("invalid value for FILE");
+
+ BufferDataFileType file_type = BufferDataFileType::kPng;
+
+ if (token->AsString() == "TEXT") {
+ file_type = BufferDataFileType::kText;
+ token = tokenizer_->NextToken();
+ } else if (token->AsString() == "BINARY") {
+ file_type = BufferDataFileType::kBinary;
+ token = tokenizer_->NextToken();
+ } else if (token->AsString() == "PNG") {
+ token = tokenizer_->NextToken();
+ }
+
+ if (!token->IsIdentifier())
+ return Result("missing file name for FILE");
+
+ buffer->SetDataFile(token->AsString(), file_type);
+
+ return {};
+ }
return Result("invalid BUFFER initializer provided");
}
diff --git a/src/amberscript/parser_buffer_test.cc b/src/amberscript/parser_buffer_test.cc
index d2f1eb1..023b9ba 100644
--- a/src/amberscript/parser_buffer_test.cc
+++ b/src/amberscript/parser_buffer_test.cc
@@ -1077,8 +1077,18 @@ TEST_F(AmberScriptParserTest, BufferMissingDataFile) {
EXPECT_EQ("1: invalid value for FILE", r.Error());
}
-TEST_F(AmberScriptParserTest, BufferDataFile) {
- std::string in = "BUFFER my_buffer FORMAT R8G8B8A8_UNORM FILE foo.png";
+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";
Parser parser;
Result r = parser.Parse(in);
@@ -1090,6 +1100,61 @@ TEST_F(AmberScriptParserTest, BufferDataFile) {
ASSERT_TRUE(buffers[0] != nullptr);
EXPECT_EQ("foo.png", buffers[0]->GetDataFile());
+ EXPECT_EQ(BufferDataFileType::kPng, buffers[0]->GetDataFileType());
+}
+
+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";
+
+ 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("data.bin", buffers[0]->GetDataFile());
+ EXPECT_EQ(BufferDataFileType::kBinary, buffers[0]->GetDataFileType());
+}
+
+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";
+
+ 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("data.txt", buffers[0]->GetDataFile());
+ EXPECT_EQ(BufferDataFileType::kText, buffers[0]->GetDataFileType());
}
} // namespace amberscript
diff --git a/src/buffer.h b/src/buffer.h
index 9d6f3d6..be44a1f 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -21,6 +21,7 @@
#include <utility>
#include <vector>
+#include "amber/amber.h"
#include "amber/result.h"
#include "amber/value.h"
#include "src/format.h"
@@ -194,14 +195,20 @@ class Buffer {
void SetMipLevels(uint32_t mip_levels) { mip_levels_ = mip_levels; }
/// Returns the number of mip levels.
- uint32_t GetMipLevels() { return mip_levels_; }
+ uint32_t GetMipLevels() const { return mip_levels_; }
/// Sets the file name for loading data into the buffer.
- void SetDataFile(std::string data_file) { data_file_ = data_file; }
+ void SetDataFile(std::string data_file, BufferDataFileType type) {
+ data_file_ = data_file;
+ data_file_type_ = type;
+ }
/// Returns the file name used to load buffer data from.
std::string GetDataFile() { return data_file_; }
+ /// Returns the file type to load buffer data from.
+ BufferDataFileType GetDataFileType() const { return data_file_type_; }
+
/// Returns a pointer to the internal storage of the buffer.
std::vector<uint8_t>* ValuePtr() { return &bytes_; }
/// Returns a pointer to the internal storage of the buffer.
@@ -259,6 +266,7 @@ class Buffer {
Sampler* sampler_ = nullptr;
ImageDimension image_dim_ = ImageDimension::kUnknown;
std::string data_file_;
+ BufferDataFileType data_file_type_ = BufferDataFileType::kUnknown;
};
} // namespace amber
diff --git a/src/executor.cc b/src/executor.cc
index 30f6fb5..3470cbe 100644
--- a/src/executor.cc
+++ b/src/executor.cc
@@ -95,11 +95,21 @@ Result Executor::Execute(Engine* engine,
continue;
BufferInfo info;
- Result r = options->delegate->LoadBufferData(buf->GetDataFile(), &info);
+ Result r = options->delegate->LoadBufferData(buf->GetDataFile(),
+ buf->GetDataFileType(), &info);
if (!r.IsSuccess())
return r;
- buf->SetData(info.values);
+ std::vector<uint8_t>* data = buf->ValuePtr();
+
+ data->clear();
+ data->reserve(info.values.size());
+ for (auto v : info.values) {
+ data->push_back(v.AsUint8());
+ }
+
+ buf->SetElementCount(static_cast<uint32_t>(data->size()) /
+ buf->GetFormat()->SizeInBytes());
buf->SetWidth(info.width);
buf->SetHeight(info.height);
}
diff --git a/tests/cases/buffer_load_binary.amber b/tests/cases/buffer_load_binary.amber
new file mode 100644
index 0000000..2eae472
--- /dev/null
+++ b/tests/cases/buffer_load_binary.amber
@@ -0,0 +1,55 @@
+#!amber
+#
+# Copyright 2020 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
+#
+# https://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 implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+SHADER compute compute_shader GLSL
+#version 430
+
+layout(set = 0, binding = 0) buffer block0 {
+ float in_data[12];
+};
+
+layout(set = 0, binding = 1) buffer block1 {
+ float out_data[12];
+};
+
+void main() {
+ for (int i = 0; i < 12; i++)
+ out_data[i] = in_data[i] * 2.0;
+}
+END
+
+BUFFER buf0 DATA_TYPE vec4<float> SIZE 3 FILE BINARY vec4data.bin
+BUFFER buf1 DATA_TYPE vec4<float> SIZE 3 FILL 0.0
+
+BUFFER ref0 DATA_TYPE vec4<float> DATA
+1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0 11.0 12.0
+END
+
+BUFFER ref1 DATA_TYPE vec4<float> DATA
+2.0 4.0 6.0 8.0 10.0 12.0 14.0 16.0 18.0 20.0 22.0 24.0
+END
+
+PIPELINE compute pipeline
+ ATTACH compute_shader
+
+ BIND BUFFER buf0 AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER buf1 AS storage DESCRIPTOR_SET 0 BINDING 1
+END
+
+RUN pipeline 1 1 1
+
+EXPECT buf0 EQ_BUFFER ref0
+EXPECT buf1 EQ_BUFFER ref1
diff --git a/tests/cases/draw_png_texture.amber b/tests/cases/draw_png_texture.amber
index c7b9885..b314624 100644
--- a/tests/cases/draw_png_texture.amber
+++ b/tests/cases/draw_png_texture.amber
@@ -34,7 +34,7 @@ void main() {
}
END
-BUFFER texture FORMAT R8G8B8A8_UNORM FILE texture.png
+BUFFER texture FORMAT R8G8B8A8_UNORM FILE PNG texture.png
BUFFER framebuffer FORMAT B8G8R8A8_UNORM
SAMPLER sampler
BUFFER position DATA_TYPE vec2<float> DATA
diff --git a/tests/cases/vec4data.bin b/tests/cases/vec4data.bin
new file mode 100644
index 0000000..1c60b14
--- /dev/null
+++ b/tests/cases/vec4data.bin
Binary files differ