aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHugues Evrard <hevrard@users.noreply.github.com>2019-01-28 17:06:16 +0000
committerdan sinclair <dj2@everburning.com>2019-01-28 12:06:16 -0500
commit970ba7a99eba1cd8d8a1ea10e4525db8b93fd284 (patch)
treee721902a817418e544d52eeb3cd7385ea214dd31
parentbca10fbe5f6fe21cae4c8cca0ccf0d07719c8670 (diff)
downloadamber-970ba7a99eba1cd8d8a1ea10e4525db8b93fd284.tar.gz
Add framebuffer dump in PPM format (#227)
This CL plumbs through the ability to dump the framebuffer into a PPM image.
-rw-r--r--include/amber/amber.h18
-rw-r--r--include/amber/value.h (renamed from src/value.h)6
-rw-r--r--samples/CMakeLists.txt1
-rw-r--r--samples/amber.cc43
-rw-r--r--samples/ppm.cc65
-rw-r--r--samples/ppm.h36
-rw-r--r--samples/ppm_test.cc94
-rw-r--r--src/amber.cc26
-rw-r--r--src/buffer.h2
-rw-r--r--src/command.h2
-rw-r--r--src/dawn/engine_dawn.cc5
-rw-r--r--src/dawn/engine_dawn.h1
-rw-r--r--src/engine.h4
-rw-r--r--src/executor_test.cc1
-rw-r--r--src/value.cc2
-rw-r--r--src/verifier_test.cc2
-rw-r--r--src/vulkan/buffer_descriptor.h2
-rw-r--r--src/vulkan/engine_vulkan.cc31
-rw-r--r--src/vulkan/engine_vulkan.h1
-rw-r--r--src/vulkan/graphics_pipeline.h2
-rw-r--r--src/vulkan/index_buffer.h2
-rw-r--r--src/vulkan/resource.h2
-rw-r--r--src/vulkan/vertex_buffer.h2
-rw-r--r--src/vulkan/vertex_buffer_test.cc2
24 files changed, 325 insertions, 27 deletions
diff --git a/include/amber/amber.h b/include/amber/amber.h
index 95eb189..c4ab3a0 100644
--- a/include/amber/amber.h
+++ b/include/amber/amber.h
@@ -23,6 +23,7 @@
#include "amber/recipe.h"
#include "amber/result.h"
+#include "amber/value.h"
namespace amber {
@@ -40,11 +41,24 @@ enum EngineType {
/// Override point of engines to add their own configuration.
struct EngineConfig {};
+struct BufferInfo {
+ /// Holds the buffer name
+ std::string buffer_name;
+ /// Holds the buffer width
+ uint32_t width;
+ /// Holds the buffer height
+ uint32_t height;
+ /// Contains the buffer internal data
+ std::vector<Value> values;
+};
+
struct Options {
/// Sets the engine to be created. Default Vulkan.
EngineType engine;
/// Holds engine specific configuration. Ownership stays with the caller.
EngineConfig* config;
+ /// Lists the buffers to extract at the end of the execution
+ std::vector<BufferInfo> extractions;
};
/// Main interface to the Amber environment.
@@ -58,13 +72,13 @@ class Amber {
/// Executes the given |recipe| with the provided |opts|. Returns a
/// |Result| which indicates if the execution succeded.
- amber::Result Execute(const amber::Recipe* recipe, const Options& opts);
+ amber::Result Execute(const amber::Recipe* recipe, Options* opts);
/// Executes the given |recipe| with the provided |opts|. Will use
/// |shader_map| to lookup shader data before attempting to compile the
/// shader if possible.
amber::Result ExecuteWithShaderData(const amber::Recipe* recipe,
- const Options& opts,
+ Options* opts,
const ShaderMap& shader_data);
};
diff --git a/src/value.h b/include/amber/value.h
index 4a1b2b5..be58ace 100644
--- a/src/value.h
+++ b/include/amber/value.h
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef SRC_VALUE_H_
-#define SRC_VALUE_H_
+#ifndef AMBER_VALUE_H_
+#define AMBER_VALUE_H_
#include <cstdint>
@@ -61,4 +61,4 @@ class Value {
} // namespace amber
-#endif // SRC_VALUE_H_
+#endif // AMBER_VALUE_H_
diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt
index 4357cb4..8bcc6f8 100644
--- a/samples/CMakeLists.txt
+++ b/samples/CMakeLists.txt
@@ -18,6 +18,7 @@ set(AMBER_SOURCES
amber.cc
config_helper.cc
log.cc
+ ppm.cc
${CMAKE_BINARY_DIR}/src/build-versions.h.fake
)
diff --git a/samples/amber.cc b/samples/amber.cc
index 4d772ab..fc69f44 100644
--- a/samples/amber.cc
+++ b/samples/amber.cc
@@ -14,6 +14,7 @@
#include <cassert>
#include <cstdlib>
+#include <fstream>
#include <iostream>
#include <set>
#include <utility>
@@ -22,6 +23,7 @@
#include "amber/amber.h"
#include "amber/recipe.h"
#include "samples/config_helper.h"
+#include "samples/ppm.h"
#include "src/build-versions.h"
#include "src/make_unique.h"
@@ -247,26 +249,51 @@ 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.image_filename.empty()) {
+ amber::BufferInfo buffer_info;
+ buffer_info.buffer_name = "framebuffer";
+ amber_options.extractions.push_back(buffer_info);
+ }
+
for (const auto& recipe_data_elem : recipe_data) {
const auto* recipe = recipe_data_elem.recipe.get();
const auto& file = recipe_data_elem.file;
amber::Amber am;
- result = am.Execute(recipe, amber_options);
+ result = am.Execute(recipe, &amber_options);
if (!result.IsSuccess()) {
std::cerr << file << ": " << result.Error() << std::endl;
failures.push_back(file);
continue;
}
- if (!options.buffer_filename.empty()) {
- // TODO(dsinclair): Write buffer file
- assert(false);
- }
-
if (!options.image_filename.empty()) {
- // TODO(dsinclair): Write image file
- assert(false);
+ std::string image;
+ for (amber::BufferInfo buffer_info : amber_options.extractions) {
+ if (buffer_info.buffer_name == "framebuffer") {
+ std::tie(result, image) = ppm::ConvertToPPM(
+ buffer_info.width, buffer_info.height, buffer_info.values);
+ break;
+ }
+ }
+ if (!result.IsSuccess()) {
+ std::cerr << result.Error() << std::endl;
+ continue;
+ }
+ std::ofstream image_file;
+ image_file.open(options.image_filename, std::ios::out | std::ios::binary);
+ if (!image_file.is_open()) {
+ std::cerr << "Cannot open file for image dump: ";
+ std::cerr << options.image_filename << std::endl;
+ continue;
+ }
+ image_file << image;
+ image_file.close();
}
}
diff --git a/samples/ppm.cc b/samples/ppm.cc
new file mode 100644
index 0000000..5602118
--- /dev/null
+++ b/samples/ppm.cc
@@ -0,0 +1,65 @@
+// 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 "samples/ppm.h"
+
+#include <cassert>
+
+#include "amber/result.h"
+#include "amber/value.h"
+
+namespace ppm {
+
+namespace {
+
+char byte0(uint32_t word) {
+ return static_cast<char>(word);
+}
+
+char byte1(uint32_t word) {
+ return static_cast<char>(word >> 8);
+}
+
+char byte2(uint32_t word) {
+ return static_cast<char>(word >> 16);
+}
+
+} // namespace
+
+std::pair<amber::Result, std::string> ConvertToPPM(
+ uint32_t width,
+ uint32_t height,
+ const std::vector<amber::Value>& values) {
+ assert(values.size() == width * height);
+
+ // Write PPM header
+ const uint32_t maximum_color_value = 255;
+ std::string image = "P6\n";
+ image += std::to_string(width) + " " + std::to_string(height) + "\n";
+ image += std::to_string(maximum_color_value) + "\n";
+
+ // Write PPM data
+ for (amber::Value value : values) {
+ const uint32_t pixel = value.AsUint32();
+ // We assume R8G8B8A8_UINT here:
+ image.push_back(byte0(pixel)); // R
+ image.push_back(byte1(pixel)); // G
+ image.push_back(byte2(pixel)); // B
+ // PPM does not support alpha channel
+ }
+
+ return std::make_pair(amber::Result(), image);
+}
+
+} // namespace ppm
diff --git a/samples/ppm.h b/samples/ppm.h
new file mode 100644
index 0000000..0eb1f8e
--- /dev/null
+++ b/samples/ppm.h
@@ -0,0 +1,36 @@
+// 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 SAMPLES_PPM_H_
+#define SAMPLES_PPM_H_
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "amber/amber.h"
+
+namespace ppm {
+
+/// Converts the image of dimensions |width| and |height| and with pixels stored
+/// in row-major order in |values| with format R8G8B8A8 into PPM format,
+/// returning the PPM binary as a string.
+std::pair<amber::Result, std::string> ConvertToPPM(
+ uint32_t width,
+ uint32_t height,
+ const std::vector<amber::Value>& values);
+
+} // namespace ppm
+
+#endif // SAMPLES_PPM_H_
diff --git a/samples/ppm_test.cc b/samples/ppm_test.cc
new file mode 100644
index 0000000..9821455
--- /dev/null
+++ b/samples/ppm_test.cc
@@ -0,0 +1,94 @@
+// 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/ppm.h"
+
+#include <algorithm>
+#include <cstring>
+#include <utility>
+#include <vector>
+
+#include "amber/result.h"
+#include "gtest/gtest.h"
+#include "src/make_unique.h"
+
+namespace amber {
+namespace {
+
+const uint8_t kExpectedPPM[] = {
+ 0x50, 0x36, 0x0a, 0x31, 0x32, 0x20, 0x36, 0x0a, 0x32, 0x35, 0x35, 0x0a,
+ 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00,
+ 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00,
+ 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00,
+ 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00,
+ 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00,
+ 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff,
+ 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff,
+ 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff,
+ 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff,
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff};
+
+} // namespace
+
+using PpmTest = testing::Test;
+
+TEST_F(PpmTest, ConvertToPPM) {
+ const uint32_t width = 12;
+ const uint32_t height = 6;
+
+ std::vector<amber::Value> data;
+
+ const uint32_t MaskRed = 0x000000FF;
+ const uint32_t MaskBlue = 0x0000FF00;
+ const uint32_t MaskAplha = 0xFF000000;
+
+ for (uint32_t y = 0; y < height; ++y) {
+ for (uint32_t x = 0; x < width; ++x) {
+ uint32_t pixel = MaskAplha;
+ if (x < width / 2) {
+ pixel |= MaskRed;
+ } else {
+ pixel |= MaskBlue;
+ }
+ if (y > height / 2) {
+ // invert colors
+ pixel = ~pixel;
+ // reset alpha to 1
+ pixel |= MaskAplha;
+ }
+ v.SetIntValue(static_cast<uint64_t>(pixel));
+ data.push_back(v);
+ }
+ }
+
+ amber::Result r;
+ std::string image;
+ std::tie(r, image) = ConvertToPPM(width, height, &data);
+
+ EXPECT_TRUE(r.IsSuccess());
+
+ // Compare
+ EXPECT_EQ(image.size(), sizeof(kExpectedPPM));
+ EXPECT_EQ(std::memcmp(image.c_str(), kExpectedPPM, sizeof(kExpectedPPM)), 0);
+}
+
+} // namespace amber
diff --git a/src/amber.cc b/src/amber.cc
index b78f0e2..2060feb 100644
--- a/src/amber.cc
+++ b/src/amber.cc
@@ -48,13 +48,13 @@ amber::Result Amber::Parse(const std::string& input, amber::Recipe* recipe) {
return {};
}
-amber::Result Amber::Execute(const amber::Recipe* recipe, const Options& opts) {
+amber::Result Amber::Execute(const amber::Recipe* recipe, Options* opts) {
ShaderMap map;
return ExecuteWithShaderData(recipe, opts, map);
}
amber::Result Amber::ExecuteWithShaderData(const amber::Recipe* recipe,
- const Options& opts,
+ Options* opts,
const ShaderMap& shader_data) {
if (!recipe)
return Result("Attempting to execute and invalid recipe");
@@ -63,11 +63,11 @@ amber::Result Amber::ExecuteWithShaderData(const amber::Recipe* recipe,
if (!script)
return Result("Recipe must contain a parsed script");
- auto engine = Engine::Create(opts.engine);
+ auto engine = Engine::Create(opts->engine);
if (!engine)
return Result("Failed to create engine");
- Result r = engine->Initialize(opts.config, script->RequiredFeatures(),
+ Result r = engine->Initialize(opts->config, script->RequiredFeatures(),
script->RequiredExtensions());
if (!r.IsSuccess())
return r;
@@ -80,6 +80,24 @@ amber::Result Amber::ExecuteWithShaderData(const amber::Recipe* recipe,
return r;
}
+ for (BufferInfo& buffer_info : opts->extractions) {
+ if (buffer_info.buffer_name == "framebuffer") {
+ ResourceInfo info;
+ r = engine->GetFrameBufferInfo(&info);
+ if (!r.IsSuccess()) {
+ engine->Shutdown();
+ return r;
+ }
+ buffer_info.width = info.image_info.width;
+ buffer_info.height = info.image_info.height;
+ r = engine->GetFrameBuffer(&(buffer_info.values));
+ if (!r.IsSuccess()) {
+ engine->Shutdown();
+ return r;
+ }
+ }
+ }
+
return engine->Shutdown();
}
diff --git a/src/buffer.h b/src/buffer.h
index 6fd4c7f..c3104a0 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -21,10 +21,10 @@
#include <utility>
#include <vector>
+#include "amber/value.h"
#include "src/buffer_data.h"
#include "src/datum_type.h"
#include "src/format.h"
-#include "src/value.h"
namespace amber {
diff --git a/src/command.h b/src/command.h
index d16ea7e..5e0b8ef 100644
--- a/src/command.h
+++ b/src/command.h
@@ -21,10 +21,10 @@
#include <vector>
#include "amber/shader_info.h"
+#include "amber/value.h"
#include "src/command_data.h"
#include "src/datum_type.h"
#include "src/pipeline_data.h"
-#include "src/value.h"
namespace amber {
diff --git a/src/dawn/engine_dawn.cc b/src/dawn/engine_dawn.cc
index 41123f3..ee994f7 100644
--- a/src/dawn/engine_dawn.cc
+++ b/src/dawn/engine_dawn.cc
@@ -456,6 +456,11 @@ Result EngineDawn::GetFrameBufferInfo(ResourceInfo* info) {
return {};
}
+Result EngineDawn::GetFrameBuffer(std::vector<Value>* values) {
+ assert(values);
+ return Result("Dawn::GetFrameBuffer not implemented");
+}
+
Result EngineDawn::GetDescriptorInfo(const uint32_t,
const uint32_t,
ResourceInfo*) {
diff --git a/src/dawn/engine_dawn.h b/src/dawn/engine_dawn.h
index 0f4d7a3..97c1b01 100644
--- a/src/dawn/engine_dawn.h
+++ b/src/dawn/engine_dawn.h
@@ -64,6 +64,7 @@ class EngineDawn : public Engine {
Result DoBuffer(const BufferCommand* cmd) override;
Result DoProcessCommands() override;
Result GetFrameBufferInfo(ResourceInfo* info) override;
+ Result GetFrameBuffer(std::vector<Value>* values) override;
Result GetDescriptorInfo(const uint32_t descriptor_set,
const uint32_t binding,
ResourceInfo* info) override;
diff --git a/src/engine.h b/src/engine.h
index ab4207d..33db6ec 100644
--- a/src/engine.h
+++ b/src/engine.h
@@ -150,6 +150,10 @@ class Engine {
/// commands have occurred e.g., DoClear, DoDrawArrays, DoDrawRect.
virtual Result GetFrameBufferInfo(ResourceInfo* info) = 0;
+ /// Copy the content of the framebuffer into |values|, each value is a pixel
+ /// in R8G8B8A8 format.
+ virtual Result GetFrameBuffer(std::vector<Value>* values) = 0;
+
/// Copy the contents of the resource bound to the given descriptor
/// and get the resource information e.g., size for buffer, width,
/// height, depth for image of descriptor given as |descriptor_set|
diff --git a/src/executor_test.cc b/src/executor_test.cc
index 1cd6e7e..024ed06 100644
--- a/src/executor_test.cc
+++ b/src/executor_test.cc
@@ -198,6 +198,7 @@ class EngineStub : public Engine {
Result DoProcessCommands() override { return {}; }
Result GetFrameBufferInfo(ResourceInfo*) override { return {}; }
+ Result GetFrameBuffer(std::vector<Value>*) override { return {}; }
Result GetDescriptorInfo(const uint32_t,
const uint32_t,
ResourceInfo*) override {
diff --git a/src/value.cc b/src/value.cc
index 60ea989..8a10582 100644
--- a/src/value.cc
+++ b/src/value.cc
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "src/value.h"
+#include "amber/value.h"
namespace amber {
diff --git a/src/verifier_test.cc b/src/verifier_test.cc
index 5f536c4..00b93c7 100644
--- a/src/verifier_test.cc
+++ b/src/verifier_test.cc
@@ -17,11 +17,11 @@
#include <vector>
#include "amber/result.h"
+#include "amber/value.h"
#include "gtest/gtest.h"
#include "src/command.h"
#include "src/datum_type.h"
#include "src/make_unique.h"
-#include "src/value.h"
#include "src/verifier.h"
namespace amber {
diff --git a/src/vulkan/buffer_descriptor.h b/src/vulkan/buffer_descriptor.h
index f0a29ee..65db9be 100644
--- a/src/vulkan/buffer_descriptor.h
+++ b/src/vulkan/buffer_descriptor.h
@@ -19,10 +19,10 @@
#include <vector>
#include "amber/result.h"
+#include "amber/value.h"
#include "amber/vulkan_header.h"
#include "src/datum_type.h"
#include "src/engine.h"
-#include "src/value.h"
#include "src/vulkan/buffer.h"
#include "src/vulkan/descriptor.h"
diff --git a/src/vulkan/engine_vulkan.cc b/src/vulkan/engine_vulkan.cc
index 451aa3f..c9a5699 100644
--- a/src/vulkan/engine_vulkan.cc
+++ b/src/vulkan/engine_vulkan.cc
@@ -402,6 +402,37 @@ Result EngineVulkan::GetFrameBufferInfo(ResourceInfo* info) {
return {};
}
+Result EngineVulkan::GetFrameBuffer(std::vector<Value>* values) {
+ values->resize(0);
+
+ ResourceInfo info;
+ GetFrameBufferInfo(&info);
+ if (info.type != ResourceInfoType::kImage) {
+ return Result(
+ "Vulkan:GetFrameBuffer() is invalid for non-image framebuffer");
+ }
+
+ // TODO(jaebaek): Support other formats
+ assert(color_frame_format_->GetFormatType() == FormatType::kR8G8B8A8_UINT);
+
+ Value pixel;
+
+ const uint8_t* cpu_memory = static_cast<const uint8_t*>(info.cpu_memory);
+ const uint32_t row_stride = info.image_info.row_stride;
+ const uint32_t texel_stride = info.image_info.texel_stride;
+
+ for (uint32_t y = 0; y < info.image_info.height; ++y) {
+ for (uint32_t x = 0; x < info.image_info.width; ++x) {
+ const uint8_t* ptr_8 = cpu_memory + (row_stride * y) + (texel_stride * x);
+ const uint32_t* ptr_32 = reinterpret_cast<const uint32_t*>(ptr_8);
+ pixel.SetIntValue(*ptr_32);
+ values->push_back(pixel);
+ }
+ }
+
+ return {};
+}
+
Result EngineVulkan::GetDescriptorInfo(const uint32_t descriptor_set,
const uint32_t binding,
ResourceInfo* info) {
diff --git a/src/vulkan/engine_vulkan.h b/src/vulkan/engine_vulkan.h
index 3c8084e..07d3cd0 100644
--- a/src/vulkan/engine_vulkan.h
+++ b/src/vulkan/engine_vulkan.h
@@ -60,6 +60,7 @@ class EngineVulkan : public Engine {
Result DoBuffer(const BufferCommand* cmd) override;
Result DoProcessCommands() override;
Result GetFrameBufferInfo(ResourceInfo* info) override;
+ Result GetFrameBuffer(std::vector<Value>* values) override;
Result GetDescriptorInfo(const uint32_t descriptor_set,
const uint32_t binding,
ResourceInfo* info) override;
diff --git a/src/vulkan/graphics_pipeline.h b/src/vulkan/graphics_pipeline.h
index 3f74725..b767efe 100644
--- a/src/vulkan/graphics_pipeline.h
+++ b/src/vulkan/graphics_pipeline.h
@@ -19,10 +19,10 @@
#include <vector>
#include "amber/result.h"
+#include "amber/value.h"
#include "amber/vulkan_header.h"
#include "src/buffer_data.h"
#include "src/format.h"
-#include "src/value.h"
#include "src/vulkan/frame_buffer.h"
#include "src/vulkan/index_buffer.h"
#include "src/vulkan/pipeline.h"
diff --git a/src/vulkan/index_buffer.h b/src/vulkan/index_buffer.h
index 626dce2..fcb44f9 100644
--- a/src/vulkan/index_buffer.h
+++ b/src/vulkan/index_buffer.h
@@ -19,9 +19,9 @@
#include <vector>
#include "amber/result.h"
+#include "amber/value.h"
#include "amber/vulkan_header.h"
#include "src/format.h"
-#include "src/value.h"
#include "src/vulkan/buffer.h"
namespace amber {
diff --git a/src/vulkan/resource.h b/src/vulkan/resource.h
index cd3845d..538bbca 100644
--- a/src/vulkan/resource.h
+++ b/src/vulkan/resource.h
@@ -19,9 +19,9 @@
#include <vector>
#include "amber/result.h"
+#include "amber/value.h"
#include "amber/vulkan_header.h"
#include "src/datum_type.h"
-#include "src/value.h"
namespace amber {
namespace vulkan {
diff --git a/src/vulkan/vertex_buffer.h b/src/vulkan/vertex_buffer.h
index ebd53a4..428bfac 100644
--- a/src/vulkan/vertex_buffer.h
+++ b/src/vulkan/vertex_buffer.h
@@ -19,9 +19,9 @@
#include <vector>
#include "amber/result.h"
+#include "amber/value.h"
#include "amber/vulkan_header.h"
#include "src/format.h"
-#include "src/value.h"
#include "src/vulkan/buffer.h"
namespace amber {
diff --git a/src/vulkan/vertex_buffer_test.cc b/src/vulkan/vertex_buffer_test.cc
index 7d0498f..0f8752f 100644
--- a/src/vulkan/vertex_buffer_test.cc
+++ b/src/vulkan/vertex_buffer_test.cc
@@ -16,10 +16,10 @@
#include <utility>
+#include "amber/value.h"
#include "gtest/gtest.h"
#include "src/format.h"
#include "src/make_unique.h"
-#include "src/value.h"
#include "src/vulkan/buffer.h"
namespace amber {