aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordan sinclair <dj2@everburning.com>2019-03-22 09:40:20 -0700
committerGitHub <noreply@github.com>2019-03-22 09:40:20 -0700
commite1a291206683118d5324f5d671f13d29aae60aa5 (patch)
treef807aacb6964e948b40b7b8a8a8083b9be996098
parentb783263992229f5c7d8b422beec09cdd4b02b31a (diff)
downloadamber-e1a291206683118d5324f5d671f13d29aae60aa5.tar.gz
Convert buffer data earlier (#394)
This CL removes the data_ pointer in the amber::Buffer object. The data is transferred into the values_ list as early as possible.
-rw-r--r--src/amberscript/parser_test.cc68
-rw-r--r--src/buffer.cc266
-rw-r--r--src/buffer.h30
-rw-r--r--src/vkscript/command_parser.cc4
-rw-r--r--src/vkscript/parser.cc2
-rw-r--r--src/vkscript/parser_test.cc58
-rw-r--r--src/vulkan/engine_vulkan.cc32
-rw-r--r--src/vulkan/graphics_pipeline.cc4
-rw-r--r--src/vulkan/graphics_pipeline.h2
-rw-r--r--src/vulkan/index_buffer.cc17
-rw-r--r--src/vulkan/index_buffer.h3
-rw-r--r--src/vulkan/vertex_buffer.cc223
-rw-r--r--src/vulkan/vertex_buffer.h12
-rw-r--r--src/vulkan/vertex_buffer_test.cc169
14 files changed, 473 insertions, 417 deletions
diff --git a/src/amberscript/parser_test.cc b/src/amberscript/parser_test.cc
index 040726c..441071c 100644
--- a/src/amberscript/parser_test.cc
+++ b/src/amberscript/parser_test.cc
@@ -993,11 +993,10 @@ END)";
EXPECT_EQ(7U * sizeof(uint32_t), buffer->GetSizeInBytes());
std::vector<uint32_t> results = {1, 2, 3, 4, 55, 99, 1234};
- const auto& data = buffer->GetData();
- ASSERT_EQ(results.size(), data.size());
+ const auto* data = buffer->GetValues<uint32_t>();
+ ASSERT_EQ(results.size(), buffer->GetSize());
for (size_t i = 0; i < results.size(); ++i) {
- ASSERT_TRUE(data[i].IsInteger());
- EXPECT_EQ(results[i], data[i].AsUint32());
+ EXPECT_EQ(results[i], data[i]);
}
}
@@ -1021,11 +1020,10 @@ TEST_F(AmberScriptParserTest, BufferFill) {
EXPECT_EQ(5U * sizeof(uint8_t), buffer->GetSizeInBytes());
std::vector<uint32_t> results = {5, 5, 5, 5, 5};
- const auto& data = buffer->GetData();
- ASSERT_EQ(results.size(), data.size());
+ const auto* data = buffer->GetValues<uint8_t>();
+ ASSERT_EQ(results.size(), buffer->GetSize());
for (size_t i = 0; i < results.size(); ++i) {
- ASSERT_TRUE(data[i].IsInteger());
- EXPECT_EQ(results[i], data[i].AsUint8());
+ EXPECT_EQ(results[i], data[i]);
}
}
@@ -1049,11 +1047,10 @@ TEST_F(AmberScriptParserTest, BufferFillFloat) {
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->GetData();
- ASSERT_EQ(results.size(), data.size());
+ const auto* data = buffer->GetValues<float>();
+ ASSERT_EQ(results.size(), buffer->GetSize());
for (size_t i = 0; i < results.size(); ++i) {
- ASSERT_TRUE(data[i].IsFloat());
- EXPECT_FLOAT_EQ(results[i], data[i].AsFloat());
+ EXPECT_FLOAT_EQ(results[i], data[i]);
}
}
@@ -1078,11 +1075,10 @@ TEST_F(AmberScriptParserTest, BufferSeries) {
EXPECT_EQ(5U * sizeof(uint8_t), buffer->GetSizeInBytes());
std::vector<uint8_t> results = {2, 3, 4, 5, 6};
- const auto& data = buffer->GetData();
- ASSERT_EQ(results.size(), data.size());
+ const auto* data = buffer->GetValues<uint8_t>();
+ ASSERT_EQ(results.size(), buffer->GetSize());
for (size_t i = 0; i < results.size(); ++i) {
- ASSERT_TRUE(data[i].IsInteger());
- EXPECT_EQ(results[i], data[i].AsUint8());
+ EXPECT_EQ(results[i], data[i]);
}
}
@@ -1108,11 +1104,10 @@ TEST_F(AmberScriptParserTest, BufferSeriesFloat) {
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->GetData();
- ASSERT_EQ(results.size(), data.size());
+ const auto* data = buffer->GetValues<float>();
+ ASSERT_EQ(results.size(), buffer->GetSize());
for (size_t i = 0; i < results.size(); ++i) {
- ASSERT_TRUE(data[i].IsFloat());
- EXPECT_FLOAT_EQ(results[i], data[i].AsFloat());
+ EXPECT_FLOAT_EQ(results[i], data[i]);
}
}
@@ -1141,11 +1136,10 @@ END)";
EXPECT_EQ(5U * sizeof(uint8_t), buffer->GetSizeInBytes());
std::vector<uint32_t> results0 = {5, 5, 5, 5, 5};
- const auto& data0 = buffer->GetData();
- ASSERT_EQ(results0.size(), data0.size());
+ const auto* data0 = buffer->GetValues<uint8_t>();
+ ASSERT_EQ(results0.size(), buffer->GetSize());
for (size_t i = 0; i < results0.size(); ++i) {
- ASSERT_TRUE(data0[i].IsInteger());
- EXPECT_EQ(results0[i], data0[i].AsUint8());
+ EXPECT_EQ(results0[i], data0[i]);
}
ASSERT_TRUE(buffers[1] != nullptr);
@@ -1157,11 +1151,10 @@ END)";
EXPECT_EQ(7U * sizeof(uint32_t), buffer->GetSizeInBytes());
std::vector<uint32_t> results1 = {1, 2, 3, 4, 55, 99, 1234};
- const auto& data1 = buffer->GetData();
- ASSERT_EQ(results1.size(), data1.size());
+ const auto* data1 = buffer->GetValues<uint32_t>();
+ ASSERT_EQ(results1.size(), buffer->GetSize());
for (size_t i = 0; i < results1.size(); ++i) {
- ASSERT_TRUE(data1[i].IsInteger());
- EXPECT_EQ(results1[i], data1[i].AsUint32());
+ EXPECT_EQ(results1[i], data1[i]);
}
}
@@ -1186,11 +1179,9 @@ BUFFER my_index_buffer DATA_TYPE vec2<int32> SIZE 5 FILL 2)";
EXPECT_EQ(5U * 2 * sizeof(int32_t), buffer->GetSizeInBytes());
std::vector<int32_t> results0 = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2};
- const auto& data0 = buffer->GetData();
- ASSERT_EQ(results0.size(), data0.size());
+ const auto* data0 = buffer->GetValues<int32_t>();
for (size_t i = 0; i < results0.size(); ++i) {
- ASSERT_TRUE(data0[i].IsInteger());
- EXPECT_EQ(results0[i], data0[i].AsInt32());
+ EXPECT_EQ(results0[i], data0[i]);
}
}
@@ -1221,11 +1212,9 @@ END
EXPECT_EQ(4U * 2 * sizeof(int32_t), buffer->GetSizeInBytes());
std::vector<int32_t> results0 = {2, 3, 4, 5, 6, 7, 8, 9};
- const auto& data0 = buffer->GetData();
- ASSERT_EQ(results0.size(), data0.size());
+ const auto* data0 = buffer->GetValues<int32_t>();
for (size_t i = 0; i < results0.size(); ++i) {
- ASSERT_TRUE(data0[i].IsInteger());
- EXPECT_EQ(results0[i], data0[i].AsInt32());
+ EXPECT_EQ(results0[i], data0[i]);
}
}
@@ -1256,11 +1245,10 @@ END
EXPECT_EQ(4U * sizeof(uint32_t), buffer->GetSizeInBytes());
std::vector<uint32_t> results0 = {4278190080, 16711680, 65280, 255};
- const auto& data0 = buffer->GetData();
- ASSERT_EQ(results0.size(), data0.size());
+ const auto* data0 = buffer->GetValues<uint32_t>();
+ ASSERT_EQ(results0.size(), buffer->GetSize());
for (size_t i = 0; i < results0.size(); ++i) {
- ASSERT_TRUE(data0[i].IsInteger());
- EXPECT_EQ(results0[i], data0[i].AsUint32());
+ EXPECT_EQ(results0[i], data0[i]);
}
}
diff --git a/src/buffer.cc b/src/buffer.cc
index eeabf76..48c35db 100644
--- a/src/buffer.cc
+++ b/src/buffer.cc
@@ -14,7 +14,187 @@
#include "src/buffer.h"
+#include <cassert>
+
namespace amber {
+namespace {
+
+// Return sign value of 32 bits float.
+uint16_t FloatSign(const uint32_t hex_float) {
+ return static_cast<uint16_t>(hex_float >> 31U);
+}
+
+// Return exponent value of 32 bits float.
+uint16_t FloatExponent(const uint32_t hex_float) {
+ uint32_t exponent = ((hex_float >> 23U) & ((1U << 8U) - 1U)) - 112U;
+ const uint32_t half_exponent_mask = (1U << 5U) - 1U;
+ assert(((exponent & ~half_exponent_mask) == 0U) && "Float exponent overflow");
+ return static_cast<uint16_t>(exponent & half_exponent_mask);
+}
+
+// Return mantissa value of 32 bits float. Note that mantissa for 32
+// bits float is 23 bits and this method must return uint32_t.
+uint32_t FloatMantissa(const uint32_t hex_float) {
+ return static_cast<uint32_t>(hex_float & ((1U << 23U) - 1U));
+}
+
+// Convert 32 bits float |value| to 16 bits float based on IEEE-754.
+uint16_t FloatToHexFloat16(const float value) {
+ const uint32_t* hex = reinterpret_cast<const uint32_t*>(&value);
+ return static_cast<uint16_t>(
+ static_cast<uint16_t>(FloatSign(*hex) << 15U) |
+ static_cast<uint16_t>(FloatExponent(*hex) << 10U) |
+ static_cast<uint16_t>(FloatMantissa(*hex) >> 13U));
+}
+
+// Convert 32 bits float |value| to 11 bits float based on IEEE-754.
+uint16_t FloatToHexFloat11(const float value) {
+ const uint32_t* hex = reinterpret_cast<const uint32_t*>(&value);
+ assert(FloatSign(*hex) == 0);
+ return static_cast<uint16_t>(
+ static_cast<uint16_t>(FloatExponent(*hex) << 6U) |
+ static_cast<uint16_t>(FloatMantissa(*hex) >> 17U));
+}
+
+// Convert 32 bits float |value| to 10 bits float based on IEEE-754.
+uint16_t FloatToHexFloat10(const float value) {
+ const uint32_t* hex = reinterpret_cast<const uint32_t*>(&value);
+ assert(FloatSign(*hex) == 0);
+ return static_cast<uint16_t>(
+ static_cast<uint16_t>(FloatExponent(*hex) << 5U) |
+ static_cast<uint16_t>(FloatMantissa(*hex) >> 18U));
+}
+
+// Convert float to small float format.
+// See https://www.khronos.org/opengl/wiki/Small_Float_Formats
+// and https://en.wikipedia.org/wiki/IEEE_754.
+//
+// Sign Exponent Mantissa Exponent-Bias
+// 16 1 5 10 15
+// 11 0 5 6 15
+// 10 0 5 5 15
+// 32 1 8 23 127
+// 64 1 11 52 1023
+//
+// 11 and 10 bits floats are always positive.
+// 14 bits float is used only RGB9_E5 format in OpenGL but it does not exist
+// in Vulkan.
+//
+// For example, 1234 in 32 bits float = 1.0011010010 * 2^10 with base 2.
+//
+// 1.0011010010 * 2^10 --> 0 (sign) / 10 + 127 (exp) / 0011010010 (Mantissa)
+// --> 0x449a4000
+uint16_t FloatToHexFloat(float value, uint8_t bits) {
+ switch (bits) {
+ case 10:
+ return FloatToHexFloat10(value);
+ case 11:
+ return FloatToHexFloat11(value);
+ case 16:
+ return FloatToHexFloat16(value);
+ }
+
+ assert(false && "Invalid bits");
+ return 0;
+}
+
+Result ValueToUint64(const Value& src, uint8_t bits, uint64_t* out) {
+ uint64_t data = 0;
+ if (src.IsInteger()) {
+ switch (bits) {
+ case 8: {
+ uint8_t* ptr = reinterpret_cast<uint8_t*>(&data);
+ *ptr = src.AsUint8();
+ break;
+ }
+ case 16: {
+ uint16_t* ptr = reinterpret_cast<uint16_t*>(&data);
+ *ptr = src.AsUint16();
+ break;
+ }
+ case 32: {
+ uint32_t* ptr = reinterpret_cast<uint32_t*>(&data);
+ *ptr = src.AsUint32();
+ break;
+ }
+ case 64: {
+ uint64_t* ptr = reinterpret_cast<uint64_t*>(&data);
+ *ptr = src.AsUint64();
+ break;
+ }
+ default: {
+ return Result("Vulkan: Invalid int bits for CopyBitsOfValueToBuffer");
+ }
+ }
+ } else {
+ if (bits == 64) {
+ double* ptr = reinterpret_cast<double*>(&data);
+ *ptr = src.AsDouble();
+ } else {
+ switch (bits) {
+ case 32: {
+ float* float_ptr = reinterpret_cast<float*>(&data);
+ *float_ptr = src.AsFloat();
+ break;
+ }
+ case 16:
+ case 11:
+ case 10: {
+ uint16_t* uint16_ptr = reinterpret_cast<uint16_t*>(&data);
+ *uint16_ptr =
+ static_cast<uint16_t>(FloatToHexFloat(src.AsFloat(), bits));
+ break;
+ }
+ default: {
+ return Result(
+ "Vulkan: Invalid float bits for CopyBitsOfValueToBuffer");
+ }
+ }
+ }
+ }
+ *out = data;
+ return {};
+}
+
+// Copy [0, bits) bits of |src| to
+// [dst_bit_offset, dst_bit_offset + bits) of |dst|. If |bits| is
+// less than 32 and the type is float, this method uses
+// FloatToHexFloat() to convert it into small bits float.
+Result CopyBitsOfValueToBuffer(uint8_t* dst,
+ const Value& src,
+ uint32_t dst_bit_offset,
+ uint8_t bits) {
+ uint64_t data = 0;
+ Result r = ValueToUint64(src, bits, &data);
+ if (!r.IsSuccess())
+ return r;
+
+ // Shift memory pointer to the start of the byte to write into.
+ while (dst_bit_offset > 7) {
+ ++dst;
+ dst_bit_offset -= 8;
+ }
+
+ // No overflow will happen. |dst_bit_offset| is based on VkFormat
+ // and if |bits| is 64, |dst_bit_offset| must be 0. No component
+ // has |bits| bigger than 64.
+ data <<= dst_bit_offset;
+
+ uint64_t* dst64 = reinterpret_cast<uint64_t*>(dst);
+ uint64_t dst_lower_bits = *dst64 & ((1UL << dst_bit_offset) - 1UL);
+ uint64_t dst_upper_bits =
+ *dst64 & ~(((1ULL << (dst_bit_offset + bits)) - 1ULL));
+
+ *dst64 = dst_lower_bits | data | dst_upper_bits;
+ return {};
+}
+
+template <typename T>
+T* ValuesAs(uint8_t* values) {
+ return reinterpret_cast<T*>(values);
+}
+
+} // namespace
Buffer::Buffer() = default;
@@ -36,10 +216,96 @@ DataBuffer::DataBuffer(BufferType type) : Buffer(type) {}
DataBuffer::~DataBuffer() = default;
+Result DataBuffer::SetData(std::vector<Value>&& data) {
+ uint32_t size = static_cast<uint32_t>(data.size()) /
+ datum_type_.ColumnCount() / datum_type_.RowCount();
+ SetSize(size);
+ values_.resize(GetSizeInBytes());
+ return CopyData(data);
+}
+
+Result DataBuffer::CopyData(const std::vector<Value>& data) {
+ uint8_t* values = values_.data();
+
+ for (const auto& val : data) {
+ if (datum_type_.IsInt8()) {
+ *(ValuesAs<int8_t>(values)) = val.AsInt8();
+ values += sizeof(int8_t);
+ } else if (datum_type_.IsInt16()) {
+ *(ValuesAs<int16_t>(values)) = val.AsInt16();
+ values += sizeof(int16_t);
+ } else if (datum_type_.IsInt32()) {
+ *(ValuesAs<int32_t>(values)) = val.AsInt32();
+ values += sizeof(int32_t);
+ } else if (datum_type_.IsInt64()) {
+ *(ValuesAs<int64_t>(values)) = val.AsInt64();
+ values += sizeof(int64_t);
+ } else if (datum_type_.IsUint8()) {
+ *(ValuesAs<uint8_t>(values)) = val.AsUint8();
+ values += sizeof(uint8_t);
+ } else if (datum_type_.IsUint16()) {
+ *(ValuesAs<uint16_t>(values)) = val.AsUint16();
+ values += sizeof(uint16_t);
+ } else if (datum_type_.IsUint32()) {
+ *(ValuesAs<uint32_t>(values)) = val.AsUint32();
+ values += sizeof(uint32_t);
+ } else if (datum_type_.IsUint64()) {
+ *(ValuesAs<uint64_t>(values)) = val.AsUint64();
+ values += sizeof(uint64_t);
+ } else if (datum_type_.IsFloat()) {
+ *(ValuesAs<float>(values)) = val.AsFloat();
+ values += sizeof(float);
+ } else if (datum_type_.IsDouble()) {
+ *(ValuesAs<double>(values)) = val.AsDouble();
+ values += sizeof(double);
+ }
+ }
+ return {};
+}
+
FormatBuffer::FormatBuffer() = default;
FormatBuffer::FormatBuffer(BufferType type) : Buffer(type) {}
FormatBuffer::~FormatBuffer() = default;
+Result FormatBuffer::SetData(std::vector<Value>&& data) {
+ SetSize(static_cast<uint32_t>(data.size()));
+ values_.resize(GetSizeInBytes());
+ return CopyData(data);
+}
+
+Result FormatBuffer::CopyData(const std::vector<Value>& data) {
+ uint8_t* ptr = values_.data();
+
+ for (uint32_t i = 0; i < data.size();) {
+ const auto pack_size = format_->GetPackSize();
+ if (pack_size) {
+ Result r = CopyBitsOfValueToBuffer(ptr, data[i], 0, pack_size);
+ if (!r.IsSuccess())
+ return r;
+
+ ptr += pack_size / 8;
+ ++i;
+ continue;
+ }
+
+ const auto& components = format_->GetComponents();
+ uint32_t bit_offset = 0;
+
+ for (uint32_t k = 0; k < components.size(); ++k) {
+ uint8_t bits = components[k].num_bits;
+ Result r = CopyBitsOfValueToBuffer(ptr, data[i + k], bit_offset, bits);
+ if (!r.IsSuccess())
+ return r;
+
+ bit_offset += bits;
+ }
+
+ i += static_cast<uint32_t>(components.size());
+ ptr += format_->GetByteSize();
+ }
+ return {};
+}
+
} // namespace amber
diff --git a/src/buffer.h b/src/buffer.h
index 8833202..056a362 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -21,6 +21,7 @@
#include <utility>
#include <vector>
+#include "amber/result.h"
#include "amber/value.h"
#include "src/buffer_data.h"
#include "src/datum_type.h"
@@ -82,9 +83,7 @@ class Buffer {
/// Sets the data into the buffer. The size will also be updated to be the
/// size of the data provided.
- virtual void SetData(std::vector<Value>&& data) { data_ = std::move(data); }
- /// Returns the vector of Values stored in the buffer.
- const std::vector<Value>& GetData() const { return data_; }
+ virtual Result SetData(std::vector<Value>&& data) = 0;
void SetMemPtr(void* ptr) { mem_ptr_ = ptr; }
@@ -102,20 +101,25 @@ class Buffer {
std::vector<uint8_t>* ValuePtr() { return &values_; }
+ template <typename T>
+ const T* GetValues() const {
+ return reinterpret_cast<const T*>(values_.data());
+ }
+
protected:
/// Create an un-typed buffer.
Buffer();
+ std::vector<uint8_t> values_;
+
private:
BufferType buffer_type_ = BufferType::kUnknown;
- std::vector<Value> data_;
std::string name_;
uint32_t size_ = 0;
uint32_t width_ = 0;
uint32_t height_ = 0;
uint8_t location_ = 0;
void* mem_ptr_ = nullptr;
- std::vector<uint8_t> values_;
};
/// A buffer class where the data is described by a |DatumType| object.
@@ -130,12 +134,7 @@ class DataBuffer : public Buffer {
uint32_t GetSizeInBytes() const override {
return GetSize() * datum_type_.SizeInBytes();
}
- void SetData(std::vector<Value>&& data) override {
- uint32_t size = static_cast<uint32_t>(data.size()) /
- datum_type_.ColumnCount() / datum_type_.RowCount();
- SetSize(size);
- Buffer::SetData(std::move(data));
- }
+ Result SetData(std::vector<Value>&& data) override;
/// Sets the DatumType of the buffer to |type|.
void SetDatumType(const DatumType& type) { datum_type_ = type; }
@@ -143,6 +142,8 @@ class DataBuffer : public Buffer {
const DatumType& GetDatumType() const { return datum_type_; }
private:
+ Result CopyData(const std::vector<Value>& data);
+
DatumType datum_type_;
};
@@ -158,10 +159,7 @@ class FormatBuffer : public Buffer {
uint32_t GetSizeInBytes() const override {
return GetSize() * format_->GetByteSize();
}
- void SetData(std::vector<Value>&& data) override {
- SetSize(static_cast<uint32_t>(data.size()));
- Buffer::SetData(std::move(data));
- }
+ Result SetData(std::vector<Value>&& data) override;
/// Sets the Format of the buffer to |format|.
void SetFormat(std::unique_ptr<Format> format) {
@@ -178,6 +176,8 @@ class FormatBuffer : public Buffer {
uint32_t GetRowStride() { return GetTexelStride() * GetWidth(); }
private:
+ Result CopyData(const std::vector<Value>& data);
+
std::unique_ptr<Format> format_;
};
diff --git a/src/vkscript/command_parser.cc b/src/vkscript/command_parser.cc
index 12d8931..890576e 100644
--- a/src/vkscript/command_parser.cc
+++ b/src/vkscript/command_parser.cc
@@ -591,7 +591,7 @@ Result CommandParser::ProcessSSBO() {
auto* buffer = pipeline_->GetBufferForBinding(set, binding);
if (!buffer) {
- auto b = MakeUnique<Buffer>(BufferType::kStorage);
+ auto b = MakeUnique<DataBuffer>(BufferType::kStorage);
b->SetName("AutoBuf-" + std::to_string(script_->GetBuffers().size()));
buffer = b.get();
script_->AddBuffer(std::move(b));
@@ -712,7 +712,7 @@ Result CommandParser::ProcessUniform() {
auto* buffer = pipeline_->GetBufferForBinding(set, binding);
if (!buffer) {
- auto b = MakeUnique<Buffer>(BufferType::kUniform);
+ auto b = MakeUnique<DataBuffer>(BufferType::kUniform);
b->SetName("AutoBuf-" + std::to_string(script_->GetBuffers().size()));
buffer = b.get();
script_->AddBuffer(std::move(b));
diff --git a/src/vkscript/parser.cc b/src/vkscript/parser.cc
index 4b4d908..79875c7 100644
--- a/src/vkscript/parser.cc
+++ b/src/vkscript/parser.cc
@@ -326,7 +326,7 @@ Result Parser::ProcessIndicesBlock(const SectionParser::Section& section) {
if (!indices.empty()) {
DatumType type;
- type.SetType(DataType::kUint16);
+ type.SetType(DataType::kUint32);
auto b = MakeUnique<DataBuffer>(BufferType::kIndex);
auto* buf = b.get();
diff --git a/src/vkscript/parser_test.cc b/src/vkscript/parser_test.cc
index 29a72fc..14b55e1 100644
--- a/src/vkscript/parser_test.cc
+++ b/src/vkscript/parser_test.cc
@@ -259,17 +259,13 @@ TEST_F(VkScriptParserTest, IndicesBlock) {
ASSERT_TRUE(buffer_ptr->IsDataBuffer());
auto buffer = buffer_ptr->AsDataBuffer();
- EXPECT_TRUE(buffer->GetDatumType().IsUint16());
+ EXPECT_TRUE(buffer->GetDatumType().IsUint32());
EXPECT_EQ(3U, buffer->GetSize());
- auto& data = buffer->GetData();
- ASSERT_EQ(3U, data.size());
-
- EXPECT_TRUE(data[0].IsInteger());
- EXPECT_EQ(1, data[0].AsUint16());
- EXPECT_TRUE(data[1].IsInteger());
- EXPECT_EQ(2, data[1].AsUint16());
- EXPECT_TRUE(data[2].IsInteger());
- EXPECT_EQ(3, data[2].AsUint16());
+
+ const auto* data = buffer->GetValues<uint32_t>();
+ EXPECT_EQ(1, data[0]);
+ EXPECT_EQ(2, data[1]);
+ EXPECT_EQ(3, data[2]);
}
TEST_F(VkScriptParserTest, IndicesBlockMultipleLines) {
@@ -289,12 +285,11 @@ TEST_F(VkScriptParserTest, IndicesBlockMultipleLines) {
ASSERT_EQ(2U, buffers.size());
ASSERT_EQ(buffers[1]->GetBufferType(), BufferType::kIndex);
- auto& data = buffers[1]->GetData();
+ const auto* data = buffers[1]->GetValues<uint32_t>();
std::vector<uint16_t> results = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
- ASSERT_EQ(results.size(), data.size());
+ ASSERT_EQ(results.size(), buffers[1]->GetSize());
for (size_t i = 0; i < results.size(); ++i) {
- EXPECT_TRUE(data[i].IsInteger());
- EXPECT_EQ(results[i], data[i].AsUint16());
+ EXPECT_EQ(results[i], data[i]);
}
}
@@ -342,13 +337,13 @@ TEST_F(VkScriptParserTest, VertexDataHeaderFormatString) {
EXPECT_EQ(static_cast<uint8_t>(0U), buffers[1]->GetLocation());
EXPECT_EQ(FormatType::kR32G32_SFLOAT,
buffers[1]->AsFormatBuffer()->GetFormat().GetFormatType());
- EXPECT_TRUE(buffers[1]->GetData().empty());
+ EXPECT_EQ(static_cast<uint32_t>(0), buffers[1]->GetSize());
ASSERT_EQ(BufferType::kVertex, buffers[2]->GetBufferType());
EXPECT_EQ(1U, buffers[2]->GetLocation());
EXPECT_EQ(FormatType::kA8B8G8R8_UNORM_PACK32,
buffers[2]->AsFormatBuffer()->GetFormat().GetFormatType());
- EXPECT_TRUE(buffers[2]->GetData().empty());
+ EXPECT_EQ(static_cast<uint32_t>(0), buffers[2]->GetSize());
}
TEST_F(VkScriptParserTest, VertexDataHeaderGlslString) {
@@ -370,7 +365,7 @@ TEST_F(VkScriptParserTest, VertexDataHeaderGlslString) {
ASSERT_EQ(2U, comps1.size());
EXPECT_EQ(FormatMode::kSFloat, comps1[0].mode);
EXPECT_EQ(FormatMode::kSFloat, comps1[1].mode);
- EXPECT_TRUE(buffers[1]->GetData().empty());
+ EXPECT_EQ(static_cast<uint32_t>(0), buffers[1]->GetSize());
ASSERT_EQ(BufferType::kVertex, buffers[2]->GetBufferType());
EXPECT_EQ(1U, buffers[2]->GetLocation());
@@ -381,7 +376,7 @@ TEST_F(VkScriptParserTest, VertexDataHeaderGlslString) {
EXPECT_EQ(FormatMode::kSInt, comps2[0].mode);
EXPECT_EQ(FormatMode::kSInt, comps2[1].mode);
EXPECT_EQ(FormatMode::kSInt, comps2[2].mode);
- EXPECT_TRUE(buffers[2]->GetData().empty());
+ EXPECT_EQ(static_cast<uint32_t>(0), buffers[2]->GetSize());
}
TEST_F(VkScriptParserTest, TestBlock) {
@@ -419,9 +414,9 @@ TEST_F(VkScriptParserTest, VertexDataRows) {
std::string block = R"([vertex data]
# Vertex data
0/R32G32B32_SFLOAT 1/R8G8B8_UNORM
--1 -1 0.25 255 0 0 # ending comment
+-1 -1 0.25 255 128 1 # ending comment
# Another Row
-0.25 -1 0.25 255 0 255
+0.25 -1 0.25 255 128 255
)";
Parser parser;
@@ -435,21 +430,19 @@ TEST_F(VkScriptParserTest, VertexDataRows) {
ASSERT_EQ(BufferType::kVertex, buffers[1]->GetBufferType());
std::vector<float> seg_0 = {-1.f, -1.f, 0.25f, 0.25f, -1.f, 0.25f};
- const auto& values_0 = buffers[1]->GetData();
- ASSERT_EQ(seg_0.size(), values_0.size());
+ const auto* values_0 = buffers[1]->GetValues<float>();
+ ASSERT_EQ(seg_0.size(), buffers[1]->GetSize());
for (size_t i = 0; i < seg_0.size(); ++i) {
- ASSERT_TRUE(values_0[i].IsFloat());
- EXPECT_FLOAT_EQ(seg_0[i], values_0[i].AsFloat());
+ EXPECT_FLOAT_EQ(seg_0[i], values_0[i]);
}
ASSERT_EQ(BufferType::kVertex, buffers[2]->GetBufferType());
- std::vector<uint8_t> seg_1 = {255, 0, 0, 255, 0, 255};
- const auto& values_1 = buffers[2]->GetData();
- ASSERT_EQ(seg_1.size(), values_1.size());
+ std::vector<uint8_t> seg_1 = {255, 128, 1, 255, 128, 255};
+ const auto* values_1 = buffers[2]->GetValues<uint8_t>();
+ ASSERT_EQ(seg_1.size(), buffers[2]->GetSize());
for (size_t i = 0; i < seg_1.size(); ++i) {
- ASSERT_TRUE(values_1[i].IsInteger());
- EXPECT_EQ(seg_1[i], values_1[i].AsUint8());
+ EXPECT_EQ(seg_1[i], values_1[i]);
}
}
@@ -496,12 +489,11 @@ TEST_F(VkScriptParserTest, VertexDataRowsWithHex) {
ASSERT_EQ(BufferType::kVertex, buffers[1]->GetBufferType());
std::vector<uint32_t> seg_0 = {0xff0000ff, 0xffff0000};
- const auto& values_0 = buffers[1]->GetData();
- ASSERT_EQ(seg_0.size(), values_0.size());
+ const auto* values_0 = buffers[1]->GetValues<uint32_t>();
+ ASSERT_EQ(seg_0.size(), buffers[1]->GetSize());
for (size_t i = 0; i < seg_0.size(); ++i) {
- ASSERT_TRUE(values_0[i].IsInteger());
- EXPECT_EQ(seg_0[i], values_0[i].AsUint32());
+ EXPECT_EQ(seg_0[i], values_0[i]);
}
}
diff --git a/src/vulkan/engine_vulkan.cc b/src/vulkan/engine_vulkan.cc
index 157873b..d4e1191 100644
--- a/src/vulkan/engine_vulkan.cc
+++ b/src/vulkan/engine_vulkan.cc
@@ -223,14 +223,16 @@ Result EngineVulkan::CreatePipeline(amber::Pipeline* pipeline) {
if (!info.vertex_buffer)
info.vertex_buffer = MakeUnique<VertexBuffer>(device_.get());
+ if (!vtex_info.buffer->IsFormatBuffer())
+ return Result("Vulkan vertex buffer is not a format buffer");
- info.vertex_buffer->SetData(static_cast<uint8_t>(vtex_info.location), fmt,
- vtex_info.buffer->GetData());
+ info.vertex_buffer->SetData(static_cast<uint8_t>(vtex_info.location),
+ vtex_info.buffer->AsFormatBuffer());
}
if (pipeline->GetIndexBuffer()) {
auto* buf = pipeline->GetIndexBuffer();
- info.vk_pipeline->AsGraphics()->SetIndexBuffer(buf->GetData());
+ info.vk_pipeline->AsGraphics()->SetIndexBuffer(buf);
}
return {};
@@ -326,15 +328,6 @@ Result EngineVulkan::DoDrawRect(const DrawRectCommand* command) {
auto* graphics = info.vk_pipeline->AsGraphics();
- // |format| is not Format for frame buffer but for vertex buffer.
- // Since draw rect command contains its vertex information and it
- // does not include a format of vertex buffer, we can choose any
- // one that is suitable. We use VK_FORMAT_R32G32_SFLOAT for it.
- Format format;
- format.SetFormatType(FormatType::kR32G32_SFLOAT);
- format.AddComponent(FormatComponentType::kR, FormatMode::kSFloat, 32);
- format.AddComponent(FormatComponentType::kG, FormatMode::kSFloat, 32);
-
float x = command->GetX();
float y = command->GetY();
float width = command->GetWidth();
@@ -363,8 +356,21 @@ Result EngineVulkan::DoDrawRect(const DrawRectCommand* command) {
values[6].SetDoubleValue(static_cast<double>(x + width));
values[7].SetDoubleValue(static_cast<double>(y));
+ // |format| is not Format for frame buffer but for vertex buffer.
+ // Since draw rect command contains its vertex information and it
+ // does not include a format of vertex buffer, we can choose any
+ // one that is suitable. We use VK_FORMAT_R32G32_SFLOAT for it.
+ auto format = MakeUnique<Format>();
+ format->SetFormatType(FormatType::kR32G32_SFLOAT);
+ format->AddComponent(FormatComponentType::kR, FormatMode::kSFloat, 32);
+ format->AddComponent(FormatComponentType::kG, FormatMode::kSFloat, 32);
+
+ auto buf = MakeUnique<FormatBuffer>();
+ buf->SetFormat(std::move(format));
+ buf->SetData(std::move(values));
+
auto vertex_buffer = MakeUnique<VertexBuffer>(device_.get());
- vertex_buffer->SetData(0, format, values);
+ vertex_buffer->SetData(0, buf.get());
DrawArraysCommand draw(command->GetPipeline(), *command->GetPipelineData());
draw.SetTopology(command->IsPatch() ? Topology::kPatchList
diff --git a/src/vulkan/graphics_pipeline.cc b/src/vulkan/graphics_pipeline.cc
index 9b2d1cc..c7f64e4 100644
--- a/src/vulkan/graphics_pipeline.cc
+++ b/src/vulkan/graphics_pipeline.cc
@@ -713,7 +713,7 @@ Result GraphicsPipeline::SendVertexBufferDataIfNeeded(
return vertex_buffer->SendVertexData(command_.get(), memory_properties_);
}
-Result GraphicsPipeline::SetIndexBuffer(const std::vector<Value>& values) {
+Result GraphicsPipeline::SetIndexBuffer(Buffer* buffer) {
if (index_buffer_) {
return Result(
"GraphicsPipeline::SetIndexBuffer must be called once when "
@@ -727,7 +727,7 @@ Result GraphicsPipeline::SetIndexBuffer(const std::vector<Value>& values) {
return guard.GetResult();
Result r =
- index_buffer_->SendIndexData(command_.get(), memory_properties_, values);
+ index_buffer_->SendIndexData(command_.get(), memory_properties_, buffer);
if (!r.IsSuccess())
return r;
diff --git a/src/vulkan/graphics_pipeline.h b/src/vulkan/graphics_pipeline.h
index c093831..d4386bf 100644
--- a/src/vulkan/graphics_pipeline.h
+++ b/src/vulkan/graphics_pipeline.h
@@ -57,7 +57,7 @@ class GraphicsPipeline : public Pipeline {
CommandPool* pool,
VkQueue queue);
- Result SetIndexBuffer(const std::vector<Value>& values);
+ Result SetIndexBuffer(Buffer* buffer);
Result Clear();
Result ClearBuffer(const VkClearValue& clear_value,
diff --git a/src/vulkan/index_buffer.cc b/src/vulkan/index_buffer.cc
index 5911744..625a40b 100644
--- a/src/vulkan/index_buffer.cc
+++ b/src/vulkan/index_buffer.cc
@@ -31,27 +31,24 @@ IndexBuffer::~IndexBuffer() = default;
Result IndexBuffer::SendIndexData(
CommandBuffer* command,
const VkPhysicalDeviceMemoryProperties& properties,
- const std::vector<Value>& values) {
+ Buffer* buffer) {
if (transfer_buffer_) {
return Result(
"IndexBuffer::SendIndexData must be called once when it is created");
}
- if (values.empty())
- return Result("IndexBuffer::SendIndexData |values| is empty");
+ if (buffer->GetSize() == 0)
+ return Result("IndexBuffer::SendIndexData |buffer| is empty");
- transfer_buffer_ = MakeUnique<TransferBuffer>(
- device_, static_cast<uint32_t>(sizeof(uint32_t) * values.size()),
- properties);
+ transfer_buffer_ =
+ MakeUnique<TransferBuffer>(device_, buffer->GetSizeInBytes(), properties);
Result r = transfer_buffer_->Initialize(VK_BUFFER_USAGE_INDEX_BUFFER_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT);
if (!r.IsSuccess())
return r;
- uint32_t* ptr =
- static_cast<uint32_t*>(transfer_buffer_->HostAccessibleMemoryPtr());
- for (const auto& value : values)
- *ptr++ = value.AsUint32();
+ std::memcpy(transfer_buffer_->HostAccessibleMemoryPtr(),
+ buffer->ValuePtr()->data(), buffer->GetSizeInBytes());
return transfer_buffer_->CopyToDevice(command);
}
diff --git a/src/vulkan/index_buffer.h b/src/vulkan/index_buffer.h
index 835c1c2..e56f058 100644
--- a/src/vulkan/index_buffer.h
+++ b/src/vulkan/index_buffer.h
@@ -21,6 +21,7 @@
#include "amber/result.h"
#include "amber/value.h"
#include "amber/vulkan_header.h"
+#include "src/buffer.h"
#include "src/format.h"
#include "src/vulkan/transfer_buffer.h"
@@ -44,7 +45,7 @@ class IndexBuffer {
// and coverts |values| as uint32 values and copies them to |buffer_|.
Result SendIndexData(CommandBuffer* command,
const VkPhysicalDeviceMemoryProperties& properties,
- const std::vector<Value>& values);
+ Buffer* buffer);
// Bind |buffer_| as index buffer if it is not nullptr.
Result BindToCommandBuffer(CommandBuffer* command);
diff --git a/src/vulkan/vertex_buffer.cc b/src/vulkan/vertex_buffer.cc
index 51d4ba3..36d5b03 100644
--- a/src/vulkan/vertex_buffer.cc
+++ b/src/vulkan/vertex_buffer.cc
@@ -24,198 +24,22 @@
namespace amber {
namespace vulkan {
-namespace {
-
-// Return sign value of 32 bits float.
-uint16_t FloatSign(const uint32_t hex_float) {
- return static_cast<uint16_t>(hex_float >> 31U);
-}
-
-// Return exponent value of 32 bits float.
-uint16_t FloatExponent(const uint32_t hex_float) {
- uint32_t exponent = ((hex_float >> 23U) & ((1U << 8U) - 1U)) - 112U;
- const uint32_t half_exponent_mask = (1U << 5U) - 1U;
- assert(((exponent & ~half_exponent_mask) == 0U) && "Float exponent overflow");
- return static_cast<uint16_t>(exponent & half_exponent_mask);
-}
-
-// Return mantissa value of 32 bits float. Note that mantissa for 32
-// bits float is 23 bits and this method must return uint32_t.
-uint32_t FloatMantissa(const uint32_t hex_float) {
- return static_cast<uint32_t>(hex_float & ((1U << 23U) - 1U));
-}
-
-// Convert 32 bits float |value| to 16 bits float based on IEEE-754.
-uint16_t FloatToHexFloat16(const float value) {
- const uint32_t* hex = reinterpret_cast<const uint32_t*>(&value);
- return static_cast<uint16_t>(
- static_cast<uint16_t>(FloatSign(*hex) << 15U) |
- static_cast<uint16_t>(FloatExponent(*hex) << 10U) |
- static_cast<uint16_t>(FloatMantissa(*hex) >> 13U));
-}
-
-// Convert 32 bits float |value| to 11 bits float based on IEEE-754.
-uint16_t FloatToHexFloat11(const float value) {
- const uint32_t* hex = reinterpret_cast<const uint32_t*>(&value);
- assert(FloatSign(*hex) == 0);
- return static_cast<uint16_t>(
- static_cast<uint16_t>(FloatExponent(*hex) << 6U) |
- static_cast<uint16_t>(FloatMantissa(*hex) >> 17U));
-}
-
-// Convert 32 bits float |value| to 10 bits float based on IEEE-754.
-uint16_t FloatToHexFloat10(const float value) {
- const uint32_t* hex = reinterpret_cast<const uint32_t*>(&value);
- assert(FloatSign(*hex) == 0);
- return static_cast<uint16_t>(
- static_cast<uint16_t>(FloatExponent(*hex) << 5U) |
- static_cast<uint16_t>(FloatMantissa(*hex) >> 18U));
-}
-
-// Convert float to small float format.
-// See https://www.khronos.org/opengl/wiki/Small_Float_Formats
-// and https://en.wikipedia.org/wiki/IEEE_754.
-//
-// Sign Exponent Mantissa Exponent-Bias
-// 16 1 5 10 15
-// 11 0 5 6 15
-// 10 0 5 5 15
-// 32 1 8 23 127
-// 64 1 11 52 1023
-//
-// 11 and 10 bits floats are always positive.
-// 14 bits float is used only RGB9_E5 format in OpenGL but it does not exist
-// in Vulkan.
-//
-// For example, 1234 in 32 bits float = 1.0011010010 * 2^10 with base 2.
-//
-// 1.0011010010 * 2^10 --> 0 (sign) / 10 + 127 (exp) / 0011010010 (Mantissa)
-// --> 0x449a4000
-uint16_t FloatToHexFloat(float value, uint8_t bits) {
- switch (bits) {
- case 10:
- return FloatToHexFloat10(value);
- case 11:
- return FloatToHexFloat11(value);
- case 16:
- return FloatToHexFloat16(value);
- }
-
- assert(false && "Invalid bits");
- return 0;
-}
-
-Result ValueToUint64(const Value& src, uint8_t bits, uint64_t* out) {
- uint64_t data = 0;
- if (src.IsInteger()) {
- switch (bits) {
- case 8: {
- uint8_t* ptr = reinterpret_cast<uint8_t*>(&data);
- *ptr = src.AsUint8();
- break;
- }
- case 16: {
- uint16_t* ptr = reinterpret_cast<uint16_t*>(&data);
- *ptr = src.AsUint16();
- break;
- }
- case 32: {
- uint32_t* ptr = reinterpret_cast<uint32_t*>(&data);
- *ptr = src.AsUint32();
- break;
- }
- case 64: {
- uint64_t* ptr = reinterpret_cast<uint64_t*>(&data);
- *ptr = src.AsUint64();
- break;
- }
- default: {
- return Result("Vulkan: Invalid int bits for CopyBitsOfValueToBuffer");
- }
- }
- } else {
- if (bits == 64) {
- double* ptr = reinterpret_cast<double*>(&data);
- *ptr = src.AsDouble();
- } else {
- switch (bits) {
- case 32: {
- float* float_ptr = reinterpret_cast<float*>(&data);
- *float_ptr = src.AsFloat();
- break;
- }
- case 16:
- case 11:
- case 10: {
- uint16_t* uint16_ptr = reinterpret_cast<uint16_t*>(&data);
- *uint16_ptr =
- static_cast<uint16_t>(FloatToHexFloat(src.AsFloat(), bits));
- break;
- }
- default: {
- return Result(
- "Vulkan: Invalid float bits for CopyBitsOfValueToBuffer");
- }
- }
- }
- }
- *out = data;
- return {};
-}
-
-// Copy [0, bits) bits of |src| to
-// [dst_bit_offset, dst_bit_offset + bits) of |dst|. If |bits| is
-// less than 32 and the type is float, this method uses
-// FloatToHexFloat() to convert it into small bits float.
-Result CopyBitsOfValueToBuffer(uint8_t* dst,
- const Value& src,
- uint32_t dst_bit_offset,
- uint8_t bits) {
- uint64_t data = 0;
- Result r = ValueToUint64(src, bits, &data);
- if (!r.IsSuccess())
- return r;
-
- // Shift memory pointer to the start of the byte to write into.
- while (dst_bit_offset > 7) {
- ++dst;
- dst_bit_offset -= 8;
- }
-
- // No overflow will happen. |dst_bit_offset| is based on VkFormat
- // and if |bits| is 64, |dst_bit_offset| must be 0. No component
- // has |bits| bigger than 64.
- data <<= dst_bit_offset;
-
- uint64_t* dst64 = reinterpret_cast<uint64_t*>(dst);
- uint64_t dst_lower_bits = *dst64 & ((1UL << dst_bit_offset) - 1UL);
- uint64_t dst_upper_bits =
- *dst64 & ~(((1ULL << (dst_bit_offset + bits)) - 1ULL));
-
- *dst64 = dst_lower_bits | data | dst_upper_bits;
- return {};
-}
-
-} // namespace
VertexBuffer::VertexBuffer(Device* device) : device_(device) {}
VertexBuffer::~VertexBuffer() = default;
-void VertexBuffer::SetData(uint8_t location,
- const Format& format,
- const std::vector<Value>& values) {
+void VertexBuffer::SetData(uint8_t location, FormatBuffer* buffer) {
vertex_attr_desc_.emplace_back();
// TODO(jaebaek): Support multiple binding
vertex_attr_desc_.back().binding = 0;
vertex_attr_desc_.back().location = location;
- vertex_attr_desc_.back().format = ToVkFormat(format.GetFormatType());
vertex_attr_desc_.back().offset = stride_in_bytes_;
+ vertex_attr_desc_.back().format =
+ ToVkFormat(buffer->GetFormat().GetFormatType());
- stride_in_bytes_ += format.GetByteSize();
-
- formats_.push_back(format);
- data_.push_back(values);
+ stride_in_bytes_ += buffer->GetFormat().GetByteSize();
+ data_.push_back(buffer);
}
Result VertexBuffer::FillVertexBufferWithData(CommandBuffer* command) {
@@ -224,36 +48,10 @@ Result VertexBuffer::FillVertexBufferWithData(CommandBuffer* command) {
static_cast<uint8_t*>(transfer_buffer_->HostAccessibleMemoryPtr());
for (uint32_t i = 0; i < GetVertexCount(); ++i) {
uint8_t* ptr = ptr_in_stride_begin;
- for (uint32_t j = 0; j < formats_.size(); ++j) {
- const auto pack_size = formats_[j].GetPackSize();
- if (pack_size) {
- Result r = CopyBitsOfValueToBuffer(ptr, data_[j][i], 0, pack_size);
- if (!r.IsSuccess())
- return r;
-
- ptr += pack_size / 8;
- continue;
- }
-
- const auto& components = formats_[j].GetComponents();
- uint32_t bit_offset = 0;
-
- for (uint32_t k = 0; k < components.size(); ++k) {
- uint8_t bits = components[k].num_bits;
- Result r = CopyBitsOfValueToBuffer(
- ptr, data_[j][i * components.size() + k], bit_offset, bits);
- if (!r.IsSuccess())
- return r;
-
- if ((k != components.size() - 1) && (bit_offset + bits >= 256)) {
- return Result(
- "Vulkan: VertexBuffer::FillVertexBufferWithData bit_offset "
- "overflow");
- }
- bit_offset += bits;
- }
-
- ptr += formats_[j].GetByteSize();
+ for (uint32_t j = 0; j < data_.size(); ++j) {
+ size_t bytes = data_[j]->GetFormat().GetByteSize();
+ std::memcpy(ptr, data_[j]->GetValues<uint8_t>() + (i * bytes), bytes);
+ ptr += bytes;
}
ptr_in_stride_begin += Get4BytesAlignedStride();
}
@@ -289,9 +87,6 @@ Result VertexBuffer::SendVertexData(
return r;
}
- if (formats_.empty() || formats_[0].GetComponents().empty())
- return Result("Vulkan::Formats for VertexBuffer is empty");
-
FillVertexBufferWithData(command);
is_vertex_data_pending_ = false;
diff --git a/src/vulkan/vertex_buffer.h b/src/vulkan/vertex_buffer.h
index cafd6b3..2e1c16a 100644
--- a/src/vulkan/vertex_buffer.h
+++ b/src/vulkan/vertex_buffer.h
@@ -21,6 +21,7 @@
#include "amber/result.h"
#include "amber/value.h"
#include "amber/vulkan_header.h"
+#include "src/buffer.h"
#include "src/format.h"
#include "src/vulkan/transfer_buffer.h"
@@ -39,9 +40,7 @@ class VertexBuffer {
const VkPhysicalDeviceMemoryProperties& properties);
bool VertexDataSent() const { return !is_vertex_data_pending_; }
- void SetData(uint8_t location,
- const Format& format,
- const std::vector<Value>& values);
+ void SetData(uint8_t location, FormatBuffer* buffer);
const std::vector<VkVertexInputAttributeDescription>& GetVkVertexInputAttr()
const {
@@ -60,9 +59,7 @@ class VertexBuffer {
uint32_t GetVertexCount() const {
if (data_.empty())
return 0;
-
- return static_cast<uint32_t>(data_[0].size() /
- formats_[0].GetComponents().size());
+ return data_[0]->GetSize();
}
void BindToCommandBuffer(CommandBuffer* command);
@@ -85,8 +82,7 @@ class VertexBuffer {
std::unique_ptr<TransferBuffer> transfer_buffer_;
uint32_t stride_in_bytes_ = 0;
- std::vector<Format> formats_;
- std::vector<std::vector<Value>> data_;
+ std::vector<FormatBuffer*> data_;
std::vector<VkVertexInputAttributeDescription> vertex_attr_desc_;
};
diff --git a/src/vulkan/vertex_buffer_test.cc b/src/vulkan/vertex_buffer_test.cc
index 5a64610..e02f53c 100644
--- a/src/vulkan/vertex_buffer_test.cc
+++ b/src/vulkan/vertex_buffer_test.cc
@@ -59,10 +59,25 @@ class VertexBufferTest : public testing::Test {
~VertexBufferTest() = default;
- Result SetData(uint8_t location,
- const Format& format,
- const std::vector<Value>& values) {
- vertex_buffer_->SetData(location, format, values);
+ Result SetIntData(uint8_t location,
+ std::unique_ptr<Format>&& format,
+ std::vector<Value> values) {
+ auto buffer = MakeUnique<FormatBuffer>();
+ buffer->SetFormat(std::move(format));
+ buffer->SetData(std::move(values));
+
+ vertex_buffer_->SetData(location, buffer.get());
+ return vertex_buffer_->SendVertexData(nullptr, kMemoryProperties);
+ }
+
+ Result SetDoubleData(uint8_t location,
+ std::unique_ptr<Format>&& format,
+ std::vector<Value> values) {
+ auto buffer = MakeUnique<FormatBuffer>();
+ buffer->SetFormat(std::move(format));
+ buffer->SetData(std::move(values));
+
+ vertex_buffer_->SetData(location, buffer.get());
return vertex_buffer_->SendVertexData(nullptr, kMemoryProperties);
}
@@ -86,13 +101,13 @@ TEST_F(VertexBufferTest, R8G8B8A8_UINT) {
values[2].SetIntValue(27);
values[3].SetIntValue(255);
- Format format;
- format.AddComponent(FormatComponentType::kR, FormatMode::kUInt, 8);
- format.AddComponent(FormatComponentType::kG, FormatMode::kUInt, 8);
- format.AddComponent(FormatComponentType::kB, FormatMode::kUInt, 8);
- format.AddComponent(FormatComponentType::kA, FormatMode::kUInt, 8);
+ auto format = MakeUnique<Format>();
+ format->AddComponent(FormatComponentType::kR, FormatMode::kUInt, 8);
+ format->AddComponent(FormatComponentType::kG, FormatMode::kUInt, 8);
+ format->AddComponent(FormatComponentType::kB, FormatMode::kUInt, 8);
+ format->AddComponent(FormatComponentType::kA, FormatMode::kUInt, 8);
- Result r = SetData(0, format, values);
+ Result r = SetIntData(0, std::move(format), values);
const uint8_t* ptr = static_cast<const uint8_t*>(GetVkBufferPtr());
EXPECT_EQ(55, ptr[0]);
EXPECT_EQ(3, ptr[1]);
@@ -107,13 +122,13 @@ TEST_F(VertexBufferTest, R16G16B16A16_UINT) {
values[2].SetIntValue(27);
values[3].SetIntValue(255);
- Format format;
- format.AddComponent(FormatComponentType::kR, FormatMode::kUInt, 16);
- format.AddComponent(FormatComponentType::kG, FormatMode::kUInt, 16);
- format.AddComponent(FormatComponentType::kB, FormatMode::kUInt, 16);
- format.AddComponent(FormatComponentType::kA, FormatMode::kUInt, 16);
+ auto format = MakeUnique<Format>();
+ format->AddComponent(FormatComponentType::kR, FormatMode::kUInt, 16);
+ format->AddComponent(FormatComponentType::kG, FormatMode::kUInt, 16);
+ format->AddComponent(FormatComponentType::kB, FormatMode::kUInt, 16);
+ format->AddComponent(FormatComponentType::kA, FormatMode::kUInt, 16);
- Result r = SetData(0, format, values);
+ Result r = SetIntData(0, std::move(format), values);
const uint16_t* ptr = static_cast<const uint16_t*>(GetVkBufferPtr());
EXPECT_EQ(55, ptr[0]);
EXPECT_EQ(3, ptr[1]);
@@ -128,13 +143,13 @@ TEST_F(VertexBufferTest, R32G32B32A32_UINT) {
values[2].SetIntValue(27);
values[3].SetIntValue(255);
- Format format;
- format.AddComponent(FormatComponentType::kR, FormatMode::kUInt, 32);
- format.AddComponent(FormatComponentType::kG, FormatMode::kUInt, 32);
- format.AddComponent(FormatComponentType::kB, FormatMode::kUInt, 32);
- format.AddComponent(FormatComponentType::kA, FormatMode::kUInt, 32);
+ auto format = MakeUnique<Format>();
+ format->AddComponent(FormatComponentType::kR, FormatMode::kUInt, 32);
+ format->AddComponent(FormatComponentType::kG, FormatMode::kUInt, 32);
+ format->AddComponent(FormatComponentType::kB, FormatMode::kUInt, 32);
+ format->AddComponent(FormatComponentType::kA, FormatMode::kUInt, 32);
- Result r = SetData(0, format, values);
+ Result r = SetIntData(0, std::move(format), values);
const uint32_t* ptr = static_cast<const uint32_t*>(GetVkBufferPtr());
EXPECT_EQ(55, ptr[0]);
EXPECT_EQ(3, ptr[1]);
@@ -149,13 +164,13 @@ TEST_F(VertexBufferTest, R64G64B64A64_UINT) {
values[2].SetIntValue(27);
values[3].SetIntValue(255);
- Format format;
- format.AddComponent(FormatComponentType::kR, FormatMode::kUInt, 64);
- format.AddComponent(FormatComponentType::kG, FormatMode::kUInt, 64);
- format.AddComponent(FormatComponentType::kB, FormatMode::kUInt, 64);
- format.AddComponent(FormatComponentType::kA, FormatMode::kUInt, 64);
+ auto format = MakeUnique<Format>();
+ format->AddComponent(FormatComponentType::kR, FormatMode::kUInt, 64);
+ format->AddComponent(FormatComponentType::kG, FormatMode::kUInt, 64);
+ format->AddComponent(FormatComponentType::kB, FormatMode::kUInt, 64);
+ format->AddComponent(FormatComponentType::kA, FormatMode::kUInt, 64);
- Result r = SetData(0, format, values);
+ Result r = SetIntData(0, std::move(format), values);
const uint64_t* ptr = static_cast<const uint64_t*>(GetVkBufferPtr());
EXPECT_EQ(55, ptr[0]);
EXPECT_EQ(3, ptr[1]);
@@ -170,13 +185,13 @@ TEST_F(VertexBufferTest, R8G8B8A8_SNORM) {
values[2].SetIntValue(static_cast<uint64_t>(-128));
values[3].SetIntValue(127);
- Format format;
- format.AddComponent(FormatComponentType::kR, FormatMode::kSNorm, 8);
- format.AddComponent(FormatComponentType::kG, FormatMode::kSNorm, 8);
- format.AddComponent(FormatComponentType::kB, FormatMode::kSNorm, 8);
- format.AddComponent(FormatComponentType::kA, FormatMode::kSNorm, 8);
+ auto format = MakeUnique<Format>();
+ format->AddComponent(FormatComponentType::kR, FormatMode::kSNorm, 8);
+ format->AddComponent(FormatComponentType::kG, FormatMode::kSNorm, 8);
+ format->AddComponent(FormatComponentType::kB, FormatMode::kSNorm, 8);
+ format->AddComponent(FormatComponentType::kA, FormatMode::kSNorm, 8);
- Result r = SetData(0, format, values);
+ Result r = SetIntData(0, std::move(format), values);
const int8_t* ptr = static_cast<const int8_t*>(GetVkBufferPtr());
EXPECT_EQ(-55, ptr[0]);
EXPECT_EQ(3, ptr[1]);
@@ -191,13 +206,13 @@ TEST_F(VertexBufferTest, R16G16B16A16_SNORM) {
values[2].SetIntValue(static_cast<uint64_t>(-27));
values[3].SetIntValue(255);
- Format format;
- format.AddComponent(FormatComponentType::kR, FormatMode::kSNorm, 16);
- format.AddComponent(FormatComponentType::kG, FormatMode::kSNorm, 16);
- format.AddComponent(FormatComponentType::kB, FormatMode::kSNorm, 16);
- format.AddComponent(FormatComponentType::kA, FormatMode::kSNorm, 16);
+ auto format = MakeUnique<Format>();
+ format->AddComponent(FormatComponentType::kR, FormatMode::kSNorm, 16);
+ format->AddComponent(FormatComponentType::kG, FormatMode::kSNorm, 16);
+ format->AddComponent(FormatComponentType::kB, FormatMode::kSNorm, 16);
+ format->AddComponent(FormatComponentType::kA, FormatMode::kSNorm, 16);
- Result r = SetData(0, format, values);
+ Result r = SetIntData(0, std::move(format), values);
const int16_t* ptr = static_cast<const int16_t*>(GetVkBufferPtr());
EXPECT_EQ(-55, ptr[0]);
EXPECT_EQ(3, ptr[1]);
@@ -212,13 +227,13 @@ TEST_F(VertexBufferTest, R32G32B32A32_SINT) {
values[2].SetIntValue(static_cast<uint64_t>(-27));
values[3].SetIntValue(255);
- Format format;
- format.AddComponent(FormatComponentType::kR, FormatMode::kSInt, 32);
- format.AddComponent(FormatComponentType::kG, FormatMode::kSInt, 32);
- format.AddComponent(FormatComponentType::kB, FormatMode::kSInt, 32);
- format.AddComponent(FormatComponentType::kA, FormatMode::kSInt, 32);
+ auto format = MakeUnique<Format>();
+ format->AddComponent(FormatComponentType::kR, FormatMode::kSInt, 32);
+ format->AddComponent(FormatComponentType::kG, FormatMode::kSInt, 32);
+ format->AddComponent(FormatComponentType::kB, FormatMode::kSInt, 32);
+ format->AddComponent(FormatComponentType::kA, FormatMode::kSInt, 32);
- Result r = SetData(0, format, values);
+ Result r = SetIntData(0, std::move(format), values);
const int32_t* ptr = static_cast<const int32_t*>(GetVkBufferPtr());
EXPECT_EQ(-55, ptr[0]);
EXPECT_EQ(3, ptr[1]);
@@ -233,13 +248,13 @@ TEST_F(VertexBufferTest, R64G64B64A64_SINT) {
values[2].SetIntValue(static_cast<uint64_t>(-27));
values[3].SetIntValue(255);
- Format format;
- format.AddComponent(FormatComponentType::kR, FormatMode::kSInt, 64);
- format.AddComponent(FormatComponentType::kG, FormatMode::kSInt, 64);
- format.AddComponent(FormatComponentType::kB, FormatMode::kSInt, 64);
- format.AddComponent(FormatComponentType::kA, FormatMode::kSInt, 64);
+ auto format = MakeUnique<Format>();
+ format->AddComponent(FormatComponentType::kR, FormatMode::kSInt, 64);
+ format->AddComponent(FormatComponentType::kG, FormatMode::kSInt, 64);
+ format->AddComponent(FormatComponentType::kB, FormatMode::kSInt, 64);
+ format->AddComponent(FormatComponentType::kA, FormatMode::kSInt, 64);
- Result r = SetData(0, format, values);
+ Result r = SetIntData(0, std::move(format), values);
const int64_t* ptr = static_cast<const int64_t*>(GetVkBufferPtr());
EXPECT_EQ(-55, ptr[0]);
EXPECT_EQ(3, ptr[1]);
@@ -269,12 +284,12 @@ TEST_F(VertexBufferTest, R16G11B10_SFLOAT) {
expected |= 380ULL << (16ULL + 11ULL);
values[2].SetDoubleValue(0.1171875);
- Format format;
- format.AddComponent(FormatComponentType::kR, FormatMode::kSFloat, 16);
- format.AddComponent(FormatComponentType::kG, FormatMode::kSFloat, 11);
- format.AddComponent(FormatComponentType::kB, FormatMode::kSFloat, 10);
+ auto format = MakeUnique<Format>();
+ format->AddComponent(FormatComponentType::kR, FormatMode::kSFloat, 16);
+ format->AddComponent(FormatComponentType::kG, FormatMode::kSFloat, 11);
+ format->AddComponent(FormatComponentType::kB, FormatMode::kSFloat, 10);
- Result r = SetData(0, format, values);
+ Result r = SetDoubleData(0, std::move(format), values);
const uint64_t* ptr = static_cast<const uint64_t*>(GetVkBufferPtr());
EXPECT_EQ(expected, *ptr);
}
@@ -301,12 +316,12 @@ TEST_F(VertexBufferTest, R10G16B11_SFLOAT) {
expected |= 1200ULL << (16ULL + 10ULL);
values[2].SetDoubleValue(14.0);
- Format format;
- format.AddComponent(FormatComponentType::kR, FormatMode::kSFloat, 10);
- format.AddComponent(FormatComponentType::kG, FormatMode::kSFloat, 16);
- format.AddComponent(FormatComponentType::kB, FormatMode::kSFloat, 11);
+ auto format = MakeUnique<Format>();
+ format->AddComponent(FormatComponentType::kR, FormatMode::kSFloat, 10);
+ format->AddComponent(FormatComponentType::kG, FormatMode::kSFloat, 16);
+ format->AddComponent(FormatComponentType::kB, FormatMode::kSFloat, 11);
- Result r = SetData(0, format, values);
+ Result r = SetDoubleData(0, std::move(format), values);
const uint64_t* ptr = static_cast<const uint64_t*>(GetVkBufferPtr());
EXPECT_EQ(expected, *ptr);
}
@@ -333,12 +348,12 @@ TEST_F(VertexBufferTest, R11G16B10_SFLOAT) {
expected |= 380ULL << (16ULL + 11ULL);
values[2].SetDoubleValue(0.1171875);
- Format format;
- format.AddComponent(FormatComponentType::kR, FormatMode::kSFloat, 11);
- format.AddComponent(FormatComponentType::kG, FormatMode::kSFloat, 16);
- format.AddComponent(FormatComponentType::kB, FormatMode::kSFloat, 10);
+ auto format = MakeUnique<Format>();
+ format->AddComponent(FormatComponentType::kR, FormatMode::kSFloat, 11);
+ format->AddComponent(FormatComponentType::kG, FormatMode::kSFloat, 16);
+ format->AddComponent(FormatComponentType::kB, FormatMode::kSFloat, 10);
- Result r = SetData(0, format, values);
+ Result r = SetDoubleData(0, std::move(format), values);
const uint64_t* ptr = static_cast<const uint64_t*>(GetVkBufferPtr());
EXPECT_EQ(expected, *ptr);
}
@@ -349,12 +364,12 @@ TEST_F(VertexBufferTest, R32G32B32_SFLOAT) {
values[1].SetDoubleValue(14.0);
values[2].SetDoubleValue(0.1171875);
- Format format;
- format.AddComponent(FormatComponentType::kR, FormatMode::kSFloat, 32);
- format.AddComponent(FormatComponentType::kG, FormatMode::kSFloat, 32);
- format.AddComponent(FormatComponentType::kB, FormatMode::kSFloat, 32);
+ auto format = MakeUnique<Format>();
+ format->AddComponent(FormatComponentType::kR, FormatMode::kSFloat, 32);
+ format->AddComponent(FormatComponentType::kG, FormatMode::kSFloat, 32);
+ format->AddComponent(FormatComponentType::kB, FormatMode::kSFloat, 32);
- Result r = SetData(0, format, values);
+ Result r = SetDoubleData(0, std::move(format), values);
const float* ptr = static_cast<const float*>(GetVkBufferPtr());
EXPECT_FLOAT_EQ(-6.0f, ptr[0]);
EXPECT_FLOAT_EQ(14.0f, ptr[1]);
@@ -367,12 +382,12 @@ TEST_F(VertexBufferTest, R64G64B64_SFLOAT) {
values[1].SetDoubleValue(14.0);
values[2].SetDoubleValue(0.1171875);
- Format format;
- format.AddComponent(FormatComponentType::kR, FormatMode::kSFloat, 64);
- format.AddComponent(FormatComponentType::kG, FormatMode::kSFloat, 64);
- format.AddComponent(FormatComponentType::kB, FormatMode::kSFloat, 64);
+ auto format = MakeUnique<Format>();
+ format->AddComponent(FormatComponentType::kR, FormatMode::kSFloat, 64);
+ format->AddComponent(FormatComponentType::kG, FormatMode::kSFloat, 64);
+ format->AddComponent(FormatComponentType::kB, FormatMode::kSFloat, 64);
- Result r = SetData(0, format, values);
+ Result r = SetDoubleData(0, std::move(format), values);
const double* ptr = static_cast<const double*>(GetVkBufferPtr());
EXPECT_DOUBLE_EQ(-6.0, ptr[0]);
EXPECT_DOUBLE_EQ(14.0, ptr[1]);