aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaebaek Seo <duke.acacia@gmail.com>2019-02-19 23:29:08 +0900
committerdan sinclair <dj2@everburning.com>2019-02-19 09:29:08 -0500
commitb3a778d1a66f34025878576b0be5e6a5c18c8b94 (patch)
tree13338d962c0fdf4c7bbcc16614bab51f3b9a10af
parent146a323c493ef0ec5705b66724f2a3636a4f1748 (diff)
downloadamber-b3a778d1a66f34025878576b0be5e6a5c18c8b94.tar.gz
Vulkan: support buffer dump (#269)
This CL adds support to dump the contents of compute buffers to a file. Fixes #36
-rw-r--r--Android.mk1
-rw-r--r--samples/amber.cc48
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/amber.cc29
-rw-r--r--src/descriptor_set_and_binding_parser.cc66
-rw-r--r--src/descriptor_set_and_binding_parser.h51
-rw-r--r--src/descriptor_set_and_binding_parser_test.cc110
7 files changed, 294 insertions, 13 deletions
diff --git a/Android.mk b/Android.mk
index f66c65e..3a3d5f5 100644
--- a/Android.mk
+++ b/Android.mk
@@ -27,6 +27,7 @@ LOCAL_SRC_FILES:= \
src/command.cc \
src/command_data.cc \
src/datum_type.cc \
+ src/descriptor_set_and_binding_parser.cc \
src/engine.cc \
src/executor.cc \
src/format.cc \
diff --git a/samples/amber.cc b/samples/amber.cc
index 6b5ceac..a1f0481 100644
--- a/samples/amber.cc
+++ b/samples/amber.cc
@@ -15,6 +15,7 @@
#include <cassert>
#include <cstdlib>
#include <fstream>
+#include <iomanip>
#include <iostream>
#include <set>
#include <utility>
@@ -34,7 +35,7 @@ struct Options {
std::string image_filename;
std::string buffer_filename;
- int64_t buffer_binding_index = 0;
+ std::vector<amber::BufferInfo> buffer_to_dump;
uint32_t engine_major = 1;
uint32_t engine_minor = 0;
bool parse_only = false;
@@ -55,7 +56,8 @@ const char kUsage[] = R"(Usage: amber [options] SCRIPT [SCRIPTS...]
-t <spirv_env> -- The target SPIR-V environment. Defaults to SPV_ENV_UNIVERSAL_1_0.
-i <filename> -- Write rendering to <filename> as a PPM image.
-b <filename> -- Write contents of a UBO or SSBO to <filename>.
- -B <buffer> -- Index of buffer to write. Defaults buffer 0.
+ -B [<desc set>:]<binding> -- Descriptor set and binding of buffer to write.
+ Default is [0:]0.
-e <engine> -- Specify graphics engine: vulkan, dawn. Default is vulkan.
-v <engine version> -- Engine version (eg, 1.1 for Vulkan). Default 1.0.
-V, --version -- Output version information for Amber and libraries.
@@ -87,14 +89,8 @@ bool ParseArgs(const std::vector<std::string>& args, Options* opts) {
std::cerr << "Missing value for -B argument." << std::endl;
return false;
}
- opts->buffer_binding_index =
- static_cast<int64_t>(strtol(args[i].c_str(), nullptr, 10));
-
- if (opts->buffer_binding_index < 0U) {
- std::cerr << "Invalid value for -B, must be 0 or greater." << std::endl;
- return false;
- }
-
+ opts->buffer_to_dump.emplace_back();
+ opts->buffer_to_dump.back().buffer_name = args[i];
} else if (arg == "-e") {
++i;
if (i >= args.size()) {
@@ -297,9 +293,10 @@ int main(int argc, const char** argv) {
amber_options.config = config.get();
- if (!options.buffer_filename.empty()) {
- // TODO(dsinclair): Write buffer file
- assert(false);
+ if (!options.buffer_filename.empty() && !options.buffer_to_dump.empty()) {
+ amber_options.extractions.insert(amber_options.extractions.end(),
+ options.buffer_to_dump.begin(),
+ options.buffer_to_dump.end());
}
if (!options.image_filename.empty()) {
@@ -343,6 +340,31 @@ int main(int argc, const char** argv) {
image_file << image;
image_file.close();
}
+
+ if (!options.buffer_filename.empty()) {
+ std::ofstream buffer_file;
+ buffer_file.open(options.buffer_filename, std::ios::out);
+ if (!buffer_file.is_open()) {
+ std::cerr << "Cannot open file for buffer dump: ";
+ std::cerr << options.buffer_filename << std::endl;
+ } else {
+ for (amber::BufferInfo buffer_info : amber_options.extractions) {
+ if (buffer_info.buffer_name == "framebuffer")
+ continue;
+
+ buffer_file << buffer_info.buffer_name << std::endl;
+ const auto& values = buffer_info.values;
+ for (size_t i = 0; i < values.size(); ++i) {
+ buffer_file << " " << std::setfill('0') << std::setw(2) << std::hex
+ << values[i].AsUint32();
+ if (i % 16 == 15)
+ buffer_file << std::endl;
+ }
+ buffer_file << std::endl;
+ }
+ buffer_file.close();
+ }
+ }
}
if (options.show_summary) {
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index c1d57d9..db63393 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -19,6 +19,7 @@ set(AMBER_SOURCES
command.cc
command_data.cc
datum_type.cc
+ descriptor_set_and_binding_parser.cc
engine.cc
executor.cc
format.cc
@@ -76,6 +77,7 @@ if (${AMBER_ENABLE_TESTS})
amberscript/parser_test.cc
buffer_test.cc
command_data_test.cc
+ descriptor_set_and_binding_parser_test.cc
executor_test.cc
format_parser_test.cc
pipeline_test.cc
diff --git a/src/amber.cc b/src/amber.cc
index 1942b46..1506112 100644
--- a/src/amber.cc
+++ b/src/amber.cc
@@ -14,10 +14,13 @@
#include "amber/amber.h"
+#include <cctype>
+#include <cstdlib>
#include <memory>
#include <string>
#include "src/amberscript/parser.h"
+#include "src/descriptor_set_and_binding_parser.h"
#include "src/engine.h"
#include "src/executor.h"
#include "src/make_unique.h"
@@ -97,6 +100,32 @@ amber::Result Amber::ExecuteWithShaderData(const amber::Recipe* recipe,
engine->Shutdown();
return r;
}
+
+ continue;
+ }
+
+ DescriptorSetAndBindingParser desc_set_and_binding_parser;
+ r = desc_set_and_binding_parser.Parse(buffer_info.buffer_name);
+ if (!r.IsSuccess()) {
+ engine->Shutdown();
+ return r;
+ }
+
+ ResourceInfo info = ResourceInfo();
+ r = engine->GetDescriptorInfo(
+ desc_set_and_binding_parser.GetDescriptorSet(),
+ desc_set_and_binding_parser.GetBinding(), &info);
+ if (!r.IsSuccess()) {
+ engine->Shutdown();
+ return r;
+ }
+
+ const uint8_t* ptr = static_cast<const uint8_t*>(info.cpu_memory);
+ auto& values = buffer_info.values;
+ for (size_t i = 0; i < info.size_in_bytes; ++i) {
+ values.emplace_back();
+ values.back().SetIntValue(*ptr);
+ ++ptr;
}
}
diff --git a/src/descriptor_set_and_binding_parser.cc b/src/descriptor_set_and_binding_parser.cc
new file mode 100644
index 0000000..0d2a1ed
--- /dev/null
+++ b/src/descriptor_set_and_binding_parser.cc
@@ -0,0 +1,66 @@
+// 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 implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/descriptor_set_and_binding_parser.h"
+
+#include <iostream>
+#include "src/tokenizer.h"
+
+namespace amber {
+
+DescriptorSetAndBindingParser::DescriptorSetAndBindingParser() = default;
+
+DescriptorSetAndBindingParser::~DescriptorSetAndBindingParser() = default;
+
+Result DescriptorSetAndBindingParser::Parse(const std::string& buffer_id) {
+ Tokenizer t(buffer_id);
+ auto token = t.NextToken();
+ if (token->IsInteger()) {
+ if (token->AsInt32() < 0) {
+ return Result(
+ "Descriptor set and binding for a buffer must be non-negative "
+ "integer, but you gave: " +
+ token->ToOriginalString());
+ }
+
+ uint32_t val = token->AsUint32();
+ token = t.NextToken();
+ if (token->IsEOS() || token->IsEOL()) {
+ descriptor_set_ = 0;
+ binding_ = val;
+ return {};
+ }
+
+ descriptor_set_ = val;
+ } else {
+ descriptor_set_ = 0;
+ }
+
+ std::cout << token->AsString() << std::endl;
+ if (!token->IsString() || token->AsString() != ",") {
+ return Result("Invalid buffer id: " + buffer_id);
+ }
+
+ token = t.NextToken();
+ if (!token->IsInteger() || token->AsInt32() < 0) {
+ return Result(
+ "Binding for a buffer must be non-negative integer, but you gave: " +
+ token->ToOriginalString());
+ }
+
+ binding_ = token->AsUint32();
+ return {};
+}
+
+} // namespace amber
diff --git a/src/descriptor_set_and_binding_parser.h b/src/descriptor_set_and_binding_parser.h
new file mode 100644
index 0000000..44a412a
--- /dev/null
+++ b/src/descriptor_set_and_binding_parser.h
@@ -0,0 +1,51 @@
+// 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 implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_DESCRIPTOR_SET_AND_BINDING_PARSER_H_
+#define SRC_DESCRIPTOR_SET_AND_BINDING_PARSER_H_
+
+#include <string>
+
+#include "amber/result.h"
+
+namespace amber {
+
+/// Class for descriptor set and binding parser.
+class DescriptorSetAndBindingParser {
+ public:
+ DescriptorSetAndBindingParser();
+ ~DescriptorSetAndBindingParser();
+
+ /// Run the parser against |buffer_id|. The result is success if the parse
+ /// completes correctly. |buffer_id| must be non-empty string. It must
+ /// be a single non-negative integer or two those integers separated by
+ /// ':'. For example, ":0", "1", and "2:3" are valid strings for |buffer_id|,
+ /// but "", "-4", ":-5", ":", "a", and "b:c" are invalid strings for
+ /// |buffer_id|.
+ Result Parse(const std::string& buffer_id);
+
+ /// Return descriptor set that is the result of Parse().
+ uint32_t GetDescriptorSet() const { return descriptor_set_; }
+
+ /// Return binding that is the result of Parse().
+ uint32_t GetBinding() const { return binding_; }
+
+ private:
+ uint32_t descriptor_set_ = 0;
+ uint32_t binding_ = 0;
+};
+
+} // namespace amber
+
+#endif // SRC_DESCRIPTOR_SET_AND_BINDING_PARSER_H_
diff --git a/src/descriptor_set_and_binding_parser_test.cc b/src/descriptor_set_and_binding_parser_test.cc
new file mode 100644
index 0000000..139a7ef
--- /dev/null
+++ b/src/descriptor_set_and_binding_parser_test.cc
@@ -0,0 +1,110 @@
+// 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 "src/descriptor_set_and_binding_parser.h"
+
+#include "gtest/gtest.h"
+
+namespace amber {
+
+using DescriptorSetAndBindingParserTest = testing::Test;
+
+TEST_F(DescriptorSetAndBindingParserTest, CommaAndBinding) {
+ DescriptorSetAndBindingParser parser;
+ Result r = parser.Parse(",1234");
+ ASSERT_TRUE(r.IsSuccess()) << r.Error();
+
+ EXPECT_EQ(0, parser.GetDescriptorSet());
+ EXPECT_EQ(1234, parser.GetBinding());
+}
+
+TEST_F(DescriptorSetAndBindingParserTest, Binding) {
+ DescriptorSetAndBindingParser parser;
+ Result r = parser.Parse("1234");
+ ASSERT_TRUE(r.IsSuccess()) << r.Error();
+
+ EXPECT_EQ(0, parser.GetDescriptorSet());
+ EXPECT_EQ(1234, parser.GetBinding());
+}
+
+TEST_F(DescriptorSetAndBindingParserTest, DescSetAndBinding) {
+ DescriptorSetAndBindingParser parser;
+ Result r = parser.Parse("1234,5678");
+ ASSERT_TRUE(r.IsSuccess()) << r.Error();
+
+ EXPECT_EQ(1234, parser.GetDescriptorSet());
+ EXPECT_EQ(5678, parser.GetBinding());
+}
+
+TEST_F(DescriptorSetAndBindingParserTest, EmptyBufferId) {
+ DescriptorSetAndBindingParser parser;
+ Result r = parser.Parse("");
+ EXPECT_EQ("Invalid buffer id: ", r.Error());
+}
+
+TEST_F(DescriptorSetAndBindingParserTest, InvalidCharacter) {
+ DescriptorSetAndBindingParser parser;
+ Result r = parser.Parse("abcd");
+ EXPECT_EQ("Invalid buffer id: abcd", r.Error());
+}
+
+TEST_F(DescriptorSetAndBindingParserTest, InvalidCharacterBetweenTwoNumbers) {
+ DescriptorSetAndBindingParser parser;
+ Result r = parser.Parse("1234a5678");
+ EXPECT_EQ("Invalid buffer id: 1234a5678", r.Error());
+}
+
+TEST_F(DescriptorSetAndBindingParserTest, InvalidCharacterAfterComma) {
+ DescriptorSetAndBindingParser parser;
+ Result r = parser.Parse("1234,a5678");
+ EXPECT_EQ(
+ "Binding for a buffer must be non-negative integer, but you gave: a5678",
+ r.Error());
+}
+
+TEST_F(DescriptorSetAndBindingParserTest, NegativeDescSet) {
+ DescriptorSetAndBindingParser parser;
+ Result r = parser.Parse("-1234,5678");
+ EXPECT_EQ(
+ "Descriptor set and binding for a buffer must be non-negative integer, "
+ "but you gave: -1234",
+ r.Error());
+}
+
+TEST_F(DescriptorSetAndBindingParserTest, NegativeBindingAfterComma) {
+ DescriptorSetAndBindingParser parser;
+ Result r = parser.Parse(",-1234");
+ EXPECT_EQ(
+ "Binding for a buffer must be non-negative integer, but you gave: -1234",
+ r.Error());
+}
+
+TEST_F(DescriptorSetAndBindingParserTest, NegativeBinding) {
+ DescriptorSetAndBindingParser parser;
+ Result r = parser.Parse("-1234");
+ EXPECT_EQ(
+ "Descriptor set and binding for a buffer must be non-negative integer, "
+ "but you gave: -1234",
+ r.Error());
+}
+
+TEST_F(DescriptorSetAndBindingParserTest, DescSetAndNegativeBinding) {
+ DescriptorSetAndBindingParser parser;
+ Result r = parser.Parse("1234,-5678");
+ EXPECT_EQ(
+ "Binding for a buffer must be non-negative integer, but you gave: -5678",
+ r.Error());
+}
+
+} // namespace amber