diff options
author | dan sinclair <dj2@everburning.com> | 2019-03-22 09:40:20 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-22 09:40:20 -0700 |
commit | e1a291206683118d5324f5d671f13d29aae60aa5 (patch) | |
tree | f807aacb6964e948b40b7b8a8a8083b9be996098 | |
parent | b783263992229f5c7d8b422beec09cdd4b02b31a (diff) | |
download | amber-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.cc | 68 | ||||
-rw-r--r-- | src/buffer.cc | 266 | ||||
-rw-r--r-- | src/buffer.h | 30 | ||||
-rw-r--r-- | src/vkscript/command_parser.cc | 4 | ||||
-rw-r--r-- | src/vkscript/parser.cc | 2 | ||||
-rw-r--r-- | src/vkscript/parser_test.cc | 58 | ||||
-rw-r--r-- | src/vulkan/engine_vulkan.cc | 32 | ||||
-rw-r--r-- | src/vulkan/graphics_pipeline.cc | 4 | ||||
-rw-r--r-- | src/vulkan/graphics_pipeline.h | 2 | ||||
-rw-r--r-- | src/vulkan/index_buffer.cc | 17 | ||||
-rw-r--r-- | src/vulkan/index_buffer.h | 3 | ||||
-rw-r--r-- | src/vulkan/vertex_buffer.cc | 223 | ||||
-rw-r--r-- | src/vulkan/vertex_buffer.h | 12 | ||||
-rw-r--r-- | src/vulkan/vertex_buffer_test.cc | 169 |
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]); |