diff options
author | dan sinclair <dsinclair@google.com> | 2019-09-25 14:36:21 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-09-25 14:36:21 -0400 |
commit | cd2efffbe0dffe2bf5ff8c34b6f26b4206a28497 (patch) | |
tree | 7377a31cd9eaec4f07f1c7730fd8c767086cfe68 | |
parent | 3c6db24b40e4bc20df93d2d623ac208d5f94f5f0 (diff) | |
download | amber-cd2efffbe0dffe2bf5ff8c34b6f26b4206a28497.tar.gz |
Add segments to format class (#669)
This CL adds the concept of 'segments' to the format class. The segments
incorporate the spacing needed for padding of the format structure as it
is read/written to memory.
-rw-r--r-- | src/amberscript/parser.cc | 10 | ||||
-rw-r--r-- | src/amberscript/parser_buffer_test.cc | 28 | ||||
-rw-r--r-- | src/buffer.cc | 87 | ||||
-rw-r--r-- | src/buffer.h | 4 | ||||
-rw-r--r-- | src/buffer_test.cc | 19 | ||||
-rw-r--r-- | src/format.cc | 107 | ||||
-rw-r--r-- | src/format.h | 55 | ||||
-rw-r--r-- | src/format_parser_test.cc | 24 | ||||
-rw-r--r-- | src/format_test.cc | 73 | ||||
-rw-r--r-- | src/verifier.cc | 290 | ||||
-rw-r--r-- | src/verifier_test.cc | 68 | ||||
-rw-r--r-- | src/vkscript/datum_type_parser.cc | 6 | ||||
-rw-r--r-- | src/vkscript/datum_type_parser_test.cc | 2 | ||||
-rw-r--r-- | src/vkscript/parser.cc | 15 | ||||
-rw-r--r-- | src/vkscript/parser_test.cc | 10 | ||||
-rw-r--r-- | src/vulkan/engine_vulkan.cc | 6 | ||||
-rw-r--r-- | src/vulkan/frame_buffer.cc | 8 | ||||
-rw-r--r-- | src/vulkan/frame_buffer.h | 2 | ||||
-rw-r--r-- | src/vulkan/graphics_pipeline.cc | 10 | ||||
-rw-r--r-- | src/vulkan/graphics_pipeline.h | 2 |
20 files changed, 472 insertions, 354 deletions
diff --git a/src/amberscript/parser.cc b/src/amberscript/parser.cc index 168df89..c3a3cf3 100644 --- a/src/amberscript/parser.cc +++ b/src/amberscript/parser.cc @@ -95,7 +95,7 @@ std::unique_ptr<Format> ToFormat(const std::string& str) { const auto& comp = sub_fmt->GetComponents()[0]; for (int i = 0; i < component_count; ++i) - fmt->AddComponent(FORMAT_TYPES[i], comp.mode, comp.num_bits); + fmt->AddComponent(FORMAT_TYPES[i], comp->mode, comp->num_bits); } else if (str.length() > 9 && str.substr(0, 3) == "mat") { if (str[4] != 'x' || str[6] != '<' || str[str.length() - 1] != '>') @@ -122,7 +122,7 @@ std::unique_ptr<Format> ToFormat(const std::string& str) { const auto& comp = sub_fmt->GetComponents()[0]; for (int i = 0; i < row_count; ++i) - fmt->AddComponent(FORMAT_TYPES[i], comp.mode, comp.num_bits); + fmt->AddComponent(FORMAT_TYPES[i], comp->mode, comp->num_bits); } else { return nullptr; @@ -137,11 +137,11 @@ std::unique_ptr<Format> ToFormat(const std::string& str) { std::string parts = "ARGB"; const auto& comps = fmt->GetComponents(); for (const auto& comp : comps) { - name += parts[static_cast<uint8_t>(comp.type)] + - std::to_string(comp.num_bits); + name += parts[static_cast<uint8_t>(comp->type)] + + std::to_string(comp->num_bits); } name += "_"; - switch (comps[0].mode) { + switch (comps[0]->mode) { case FormatMode::kUNorm: case FormatMode::kUFloat: case FormatMode::kUScaled: diff --git a/src/amberscript/parser_buffer_test.cc b/src/amberscript/parser_buffer_test.cc index 47f15a0..7ae7b9b 100644 --- a/src/amberscript/parser_buffer_test.cc +++ b/src/amberscript/parser_buffer_test.cc @@ -388,18 +388,18 @@ TEST_F(AmberScriptParserTest, BufferFormat) { auto& comps = fmt->GetComponents(); ASSERT_EQ(4U, comps.size()); - EXPECT_EQ(FormatComponentType::kR, comps[0].type); - EXPECT_EQ(FormatMode::kSInt, comps[0].mode); - EXPECT_EQ(32U, comps[0].num_bits); - EXPECT_EQ(FormatComponentType::kG, comps[1].type); - EXPECT_EQ(FormatMode::kSInt, comps[1].mode); - EXPECT_EQ(32U, comps[1].num_bits); - EXPECT_EQ(FormatComponentType::kB, comps[2].type); - EXPECT_EQ(FormatMode::kSInt, comps[2].mode); - EXPECT_EQ(32U, comps[2].num_bits); - EXPECT_EQ(FormatComponentType::kA, comps[3].type); - EXPECT_EQ(FormatMode::kSInt, comps[3].mode); - EXPECT_EQ(32U, comps[3].num_bits); + EXPECT_EQ(FormatComponentType::kR, comps[0]->type); + EXPECT_EQ(FormatMode::kSInt, comps[0]->mode); + EXPECT_EQ(32U, comps[0]->num_bits); + EXPECT_EQ(FormatComponentType::kG, comps[1]->type); + EXPECT_EQ(FormatMode::kSInt, comps[1]->mode); + EXPECT_EQ(32U, comps[1]->num_bits); + EXPECT_EQ(FormatComponentType::kB, comps[2]->type); + EXPECT_EQ(FormatMode::kSInt, comps[2]->mode); + EXPECT_EQ(32U, comps[2]->num_bits); + EXPECT_EQ(FormatComponentType::kA, comps[3]->type); + EXPECT_EQ(FormatMode::kSInt, comps[3]->mode); + EXPECT_EQ(32U, comps[3]->num_bits); } struct BufferParseError { @@ -520,8 +520,8 @@ TEST_P(AmberScriptParserBufferDataTypeTest, BufferTypes) { auto fmt = buffer->GetFormat(); EXPECT_EQ(test_data.row_count, fmt->RowCount()); EXPECT_EQ(test_data.column_count, fmt->ColumnCount()); - EXPECT_EQ(test_data.type, fmt->GetComponents()[0].mode); - EXPECT_EQ(test_data.num_bits, fmt->GetComponents()[0].num_bits); + EXPECT_EQ(test_data.type, fmt->GetComponents()[0]->mode); + EXPECT_EQ(test_data.num_bits, fmt->GetComponents()[0]->num_bits); } INSTANTIATE_TEST_SUITE_P( AmberScriptParserTestsDataType, diff --git a/src/buffer.cc b/src/buffer.cc index 63ee0c1..18e5c4e 100644 --- a/src/buffer.cc +++ b/src/buffer.cc @@ -60,33 +60,33 @@ double Sub(const uint8_t* buf1, const uint8_t* buf2) { *reinterpret_cast<const T*>(buf2)); } -double CalculateDiff(const Format::Component& comp, +double CalculateDiff(const Format::Component* comp, const uint8_t* buf1, const uint8_t* buf2) { - if (comp.IsInt8()) + if (comp->IsInt8()) return Sub<int8_t>(buf1, buf2); - if (comp.IsInt16()) + if (comp->IsInt16()) return Sub<int16_t>(buf1, buf2); - if (comp.IsInt32()) + if (comp->IsInt32()) return Sub<int32_t>(buf1, buf2); - if (comp.IsInt64()) + if (comp->IsInt64()) return Sub<int64_t>(buf1, buf2); - if (comp.IsUint8()) + if (comp->IsUint8()) return Sub<uint8_t>(buf1, buf2); - if (comp.IsUint16()) + if (comp->IsUint16()) return Sub<uint16_t>(buf1, buf2); - if (comp.IsUint32()) + if (comp->IsUint32()) return Sub<uint32_t>(buf1, buf2); - if (comp.IsUint64()) + if (comp->IsUint64()) return Sub<uint64_t>(buf1, buf2); // TOOD(dsinclair): Handle float16 ... - if (comp.IsFloat16()) { + if (comp->IsFloat16()) { assert(false && "Float16 suppport not implemented"); return 0.0; } - if (comp.IsFloat()) + if (comp->IsFloat()) return Sub<float>(buf1, buf2); - if (comp.IsDouble()) + if (comp->IsDouble()) return Sub<double>(buf1, buf2); assert(false && "NOTREACHED"); @@ -156,20 +156,15 @@ std::vector<double> Buffer::CalculateDiffs(const Buffer* buffer) const { auto* buf_1_ptr = GetValues<uint8_t>(); auto* buf_2_ptr = buffer->GetValues<uint8_t>(); - auto comps = format_->GetComponents(); - + const auto& segments = format_->GetSegments(); for (size_t i = 0; i < ElementCount(); ++i) { - for (size_t j = 0; j < format_->ColumnCount(); ++j) { - auto* buf_1_row_ptr = buf_1_ptr; - auto* buf_2_row_ptr = buf_2_ptr; - for (size_t k = 0; k < format_->RowCount(); ++k) { - diffs.push_back(CalculateDiff(comps[k], buf_1_row_ptr, buf_2_row_ptr)); - - buf_1_row_ptr += comps[k].SizeInBytes(); - buf_2_row_ptr += comps[k].SizeInBytes(); - } - buf_1_ptr += format_->SizeInBytesPerRow(); - buf_2_ptr += format_->SizeInBytesPerRow(); + for (const auto& seg : segments) { + if (!seg.IsPadding()) + diffs.push_back( + CalculateDiff(seg.GetComponent(), buf_1_ptr, buf_2_ptr)); + + buf_1_ptr += seg.GetComponent()->SizeInBytes(); + buf_2_ptr += seg.GetComponent()->SizeInBytes(); } } @@ -248,7 +243,7 @@ Result Buffer::SetDataWithOffset(const std::vector<Value>& data, return Result("Mismatched number of items in buffer"); uint8_t* ptr = bytes_.data() + offset; - const auto& components = format_->GetComponents(); + const auto& segments = format_->GetSegments(); for (uint32_t i = 0; i < data.size();) { const auto pack_size = format_->GetPackSize(); if (pack_size) { @@ -266,65 +261,63 @@ Result Buffer::SetDataWithOffset(const std::vector<Value>& data, continue; } - for (size_t k = 0; k < format_->RowCount(); ++k) { - ptr += WriteValueFromComponent(data[i], components[k], ptr); - ++i; - } - // For formats which we've padded to the the layout, make sure we skip over - // the space in the buffer. - size_t pad = format_->ValuesPerRow() - components.size(); - for (size_t j = 0; j < pad; ++j) { + for (const auto& seg : segments) { Value v; - ptr += WriteValueFromComponent(v, components[0], ptr); + if (!seg.IsPadding()) { + v = data[i]; + ++i; + } + + ptr += WriteValueFromComponent(v, seg.GetComponent(), ptr); } } return {}; } uint32_t Buffer::WriteValueFromComponent(const Value& value, - const Format::Component& comp, + const Format::Component* comp, uint8_t* ptr) { - if (comp.IsInt8()) { + if (comp->IsInt8()) { *(ValuesAs<int8_t>(ptr)) = value.AsInt8(); return sizeof(int8_t); } - if (comp.IsInt16()) { + if (comp->IsInt16()) { *(ValuesAs<int16_t>(ptr)) = value.AsInt16(); return sizeof(int16_t); } - if (comp.IsInt32()) { + if (comp->IsInt32()) { *(ValuesAs<int32_t>(ptr)) = value.AsInt32(); return sizeof(int32_t); } - if (comp.IsInt64()) { + if (comp->IsInt64()) { *(ValuesAs<int64_t>(ptr)) = value.AsInt64(); return sizeof(int64_t); } - if (comp.IsUint8()) { + if (comp->IsUint8()) { *(ValuesAs<uint8_t>(ptr)) = value.AsUint8(); return sizeof(uint8_t); } - if (comp.IsUint16()) { + if (comp->IsUint16()) { *(ValuesAs<uint16_t>(ptr)) = value.AsUint16(); return sizeof(uint16_t); } - if (comp.IsUint32()) { + if (comp->IsUint32()) { *(ValuesAs<uint32_t>(ptr)) = value.AsUint32(); return sizeof(uint32_t); } - if (comp.IsUint64()) { + if (comp->IsUint64()) { *(ValuesAs<uint64_t>(ptr)) = value.AsUint64(); return sizeof(uint64_t); } - if (comp.IsFloat()) { + if (comp->IsFloat()) { *(ValuesAs<float>(ptr)) = value.AsFloat(); return sizeof(float); } - if (comp.IsDouble()) { + if (comp->IsDouble()) { *(ValuesAs<double>(ptr)) = value.AsDouble(); return sizeof(double); } - if (comp.IsFloat16()) { + if (comp->IsFloat16()) { *(ValuesAs<uint16_t>(ptr)) = FloatToHexFloat16(value.AsFloat()); return sizeof(uint16_t); } diff --git a/src/buffer.h b/src/buffer.h index b95a3d4..9fb6484 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -94,7 +94,7 @@ class Buffer { // | Value | Value | Value | Value | ValueCount == 4 // | | | | | | | | | | | | | | | | | SizeInBytes == 16 // Note, the SizeInBytes maybe be greater then the size of the values. If - // the format IsStd140() and there are 3 rows, the SizeInBytes will be + // the format is std140 and there are 3 rows, the SizeInBytes will be // inflated to 4 values per row, instead of 3. /// Sets the number of elements in the buffer. @@ -198,7 +198,7 @@ class Buffer { private: uint32_t WriteValueFromComponent(const Value& value, - const Format::Component& comp, + const Format::Component* comp, uint8_t* ptr); // Calculates the difference between the value stored in this buffer and diff --git a/src/buffer_test.cc b/src/buffer_test.cc index f9c7fc9..eba1bc5 100644 --- a/src/buffer_test.cc +++ b/src/buffer_test.cc @@ -69,7 +69,7 @@ TEST_F(BufferTest, SizeFromDataDoesNotOverrideSize) { EXPECT_EQ(20 * sizeof(float), b.GetSizeInBytes()); } -TEST_F(BufferTest, SizeMatrix) { +TEST_F(BufferTest, SizeMatrixStd430) { FormatParser fp; auto fmt = fp.Parse("R16G16_SINT"); fmt->SetColumnCount(3); @@ -83,7 +83,22 @@ TEST_F(BufferTest, SizeMatrix) { EXPECT_EQ(60 * sizeof(int16_t), b.GetSizeInBytes()); } -TEST_F(BufferTest, SizeMatrixPadded) { +TEST_F(BufferTest, SizeMatrixStd140) { + FormatParser fp; + auto fmt = fp.Parse("R16G16_SINT"); + fmt->SetColumnCount(3); + fmt->SetIsStd140(); + + Buffer b(BufferType::kColor); + b.SetFormat(std::move(fmt)); + b.SetElementCount(10); + + EXPECT_EQ(10, b.ElementCount()); + EXPECT_EQ(120, b.ValueCount()); + EXPECT_EQ(120 * sizeof(int16_t), b.GetSizeInBytes()); +} + +TEST_F(BufferTest, SizeMatrixPaddedStd430) { FormatParser fp; auto fmt = fp.Parse("R32G32B32_SINT"); fmt->SetColumnCount(3); diff --git a/src/format.cc b/src/format.cc index de2ef06..63e017e 100644 --- a/src/format.cc +++ b/src/format.cc @@ -20,38 +20,47 @@ namespace amber { Format::Format() = default; -Format::Format(const Format&) = default; +Format::Format(const Format& b) { + type_ = b.type_; + is_std140_ = b.is_std140_; + pack_size_in_bytes_ = b.pack_size_in_bytes_; + column_count_ = b.column_count_; + + for (const auto& comp : b.components_) { + components_.push_back( + MakeUnique<Component>(comp->type, comp->mode, comp->num_bits)); + } + RebuildSegments(); +} Format::~Format() = default; -uint32_t Format::SizeInBytesPerRow() const { - uint32_t bits = 0; - for (const auto& comp : components_) - bits += comp.num_bits; - - uint32_t inflate = 0; - // Std140 always has 4 elements. std430 expands 3 elements to 4. - if ((is_std140_ && column_count_ > 1) || components_.size() == 3) - inflate = 4U - static_cast<uint32_t>(components_.size()); +Format& Format::operator=(const Format& b) { + type_ = b.type_; + is_std140_ = b.is_std140_; + pack_size_in_bytes_ = b.pack_size_in_bytes_; + column_count_ = b.column_count_; - for (uint32_t i = 0; i < inflate; ++i) - bits += components_[0].num_bits; - - uint32_t bytes_per_element = bits / 8; - // Odd number of bits, inflate byte count to accommodate - if ((bits % 8) != 0) - bytes_per_element += 1; + for (const auto& comp : b.components_) { + components_.push_back( + MakeUnique<Component>(comp->type, comp->mode, comp->num_bits)); + } + RebuildSegments(); - return bytes_per_element; + return *this; } uint32_t Format::SizeInBytes() const { - return SizeInBytesPerRow() * column_count_; + uint32_t size = 0; + for (const auto& seg : segments_) + size += static_cast<uint32_t>(seg.GetComponent()->SizeInBytes()); + + return size; } bool Format::AreAllComponents(FormatMode mode, uint32_t bits) const { for (const auto& comp : components_) { - if (comp.mode != mode || comp.num_bits != bits) + if (comp->mode != mode || comp->num_bits != bits) return false; } return true; @@ -67,13 +76,65 @@ bool Format::Equal(const Format* b) const { return false; for (uint32_t i = 0; i < components_.size(); ++i) { - if (components_[i].type != b->components_[i].type || - components_[i].mode != b->components_[i].mode || - components_[i].num_bits != b->components_[i].num_bits) { + if (components_[i]->type != b->components_[i]->type || + components_[i]->mode != b->components_[i]->mode || + components_[i]->num_bits != b->components_[i]->num_bits) { return false; } } return true; } +uint32_t Format::InputNeededPerElement() const { + uint32_t count = 0; + for (const auto& seg : segments_) { + if (seg.IsPadding()) + continue; + + count += 1; + } + return count; +} + +void Format::AddComponent(FormatComponentType type, + FormatMode mode, + uint8_t bits) { + components_.push_back(MakeUnique<Component>(type, mode, bits)); + RebuildSegments(); +} + +void Format::SetColumnCount(uint32_t c) { + column_count_ = c; + RebuildSegments(); +} + +void Format::SetIsStd140() { + is_std140_ = true; + RebuildSegments(); +} + +void Format::RebuildSegments() { + segments_.clear(); + + for (size_t i = 0; i < column_count_; ++i) { + for (size_t k = 0; k < components_.size(); ++k) { + segments_.push_back(Segment{components_[k].get()}); + } + + // In std140 a matrix (column count > 1) has each row stored like an array + // which rounds up to a vec4. + // + // In std140 and std430 a vector of size 3N will round up to a vector of 4N. + if ((is_std140_ && column_count_ > 1) || RowCount() == 3) { + for (size_t k = 0; k < (4 - RowCount()); ++k) { + // TODO(dsinclair): This component will be wrong if all the components + // aren't the same size. This will be the case when we have struct + // support .... + segments_.push_back(Segment{components_[0].get()}); + segments_.back().SetIsPadding(); + } + } + } +} + } // namespace amber diff --git a/src/format.h b/src/format.h index d4dbe04..ab1eb37 100644 --- a/src/format.h +++ b/src/format.h @@ -20,6 +20,7 @@ #include <vector> #include "src/format_data.h" +#include "src/make_unique.h" namespace amber { @@ -98,12 +99,30 @@ class Format { } }; + class Segment { + public: + explicit Segment(Component* component) : component_(component) {} + Segment(const Segment&) = default; + ~Segment() = default; + + Segment& operator=(const Segment&) = default; + + void SetIsPadding() { is_padding_ = true; } + bool IsPadding() const { return is_padding_; } + + Component* GetComponent() const { return component_; } + + private: + Component* component_; + bool is_padding_ = false; + }; + /// Creates a format of unknown type. Format(); Format(const Format&); ~Format(); - Format& operator=(const Format&) = default; + Format& operator=(const Format&); /// Returns true if |b| describes the same format as this object. bool Equal(const Format* b) const; @@ -114,8 +133,7 @@ class Format { void SetFormatType(FormatType type) { type_ = type; } FormatType GetFormatType() const { return type_; } - void SetIsStd140() { is_std140_ = true; } - bool IsStd140() const { return is_std140_; } + void SetIsStd140(); /// Set the number of bytes this format is packed into, if provided. void SetPackSize(uint8_t size_in_bytes) { @@ -124,15 +142,16 @@ class Format { /// Retrieves the number of bytes this format is packed into. uint8_t GetPackSize() const { return pack_size_in_bytes_; } - void AddComponent(FormatComponentType type, FormatMode mode, uint8_t bits) { - components_.emplace_back(type, mode, bits); + void AddComponent(FormatComponentType type, FormatMode mode, uint8_t bits); + const std::vector<std::unique_ptr<Component>>& GetComponents() const { + return components_; } - const std::vector<Component>& GetComponents() const { return components_; } + + /// The segment is the individual pieces of the components including padding. + const std::vector<Segment>& GetSegments() const { return segments_; } /// Returns the number of bytes this format requires. uint32_t SizeInBytes() const; - /// Returns the number of bytes per single row this format requires. - uint32_t SizeInBytesPerRow() const; bool IsFormatKnown() const { return type_ != FormatType::kUnknown; } bool HasStencilComponent() const { @@ -145,23 +164,19 @@ class Format { /// Returns the number of input values required for an item of this format. /// This differs from ValuesPerElement because it doesn't take padding into /// account. - uint32_t InputNeededPerElement() const { return RowCount() * column_count_; } + uint32_t InputNeededPerElement() const; - /// Returns the number of values for a given row. - uint32_t ValuesPerRow() const { - if ((is_std140_ && column_count_ > 1) || RowCount() == 3) - return 4; - return RowCount(); + /// Returns the number of values for a given row, including padding. + uint32_t ValuesPerElement() const { + return static_cast<uint32_t>(segments_.size()); } - /// Returns the number of values for each instance of this format. - uint32_t ValuesPerElement() const { return ValuesPerRow() * column_count_; } - + /// Returns the number of values for a given row, excluding padding. uint32_t RowCount() const { return static_cast<uint32_t>(components_.size()); } uint32_t ColumnCount() const { return column_count_; } - void SetColumnCount(uint32_t c) { column_count_ = c; } + void SetColumnCount(uint32_t c); /// Returns true if all components of this format are an 8 bit signed int. bool IsInt8() const { return AreAllComponents(FormatMode::kSInt, 8); } @@ -186,12 +201,14 @@ class Format { private: bool AreAllComponents(FormatMode mode, uint32_t bits) const; + void RebuildSegments(); FormatType type_ = FormatType::kUnknown; bool is_std140_ = false; uint8_t pack_size_in_bytes_ = 0; uint32_t column_count_ = 1; - std::vector<Component> components_; + std::vector<std::unique_ptr<Component>> components_; + std::vector<Segment> segments_; }; } // namespace amber diff --git a/src/format_parser_test.cc b/src/format_parser_test.cc index 0f8a41f..5f71fed 100644 --- a/src/format_parser_test.cc +++ b/src/format_parser_test.cc @@ -1187,9 +1187,9 @@ TEST_F(FormatParserTest, Formats) { ASSERT_EQ(fmt.component_count, comps.size()); for (size_t i = 0; i < fmt.component_count; ++i) { - EXPECT_EQ(fmt.components[i].type, comps[i].type) << fmt.name; - EXPECT_EQ(fmt.components[i].mode, comps[i].mode) << fmt.name; - EXPECT_EQ(fmt.components[i].num_bits, comps[i].num_bits) << fmt.name; + EXPECT_EQ(fmt.components[i].type, comps[i]->type) << fmt.name; + EXPECT_EQ(fmt.components[i].mode, comps[i]->mode) << fmt.name; + EXPECT_EQ(fmt.components[i].num_bits, comps[i]->num_bits) << fmt.name; } } } // NOLINT(readability/fn_size) @@ -1217,15 +1217,15 @@ TEST_F(FormatParserTest, GlslString) { auto& comps = format->GetComponents(); ASSERT_EQ(3U, comps.size()); - EXPECT_EQ(FormatComponentType::kR, comps[0].type); - EXPECT_EQ(FormatMode::kSFloat, comps[0].mode); - EXPECT_EQ(32U, comps[0].num_bits); - EXPECT_EQ(FormatComponentType::kG, comps[1].type); - EXPECT_EQ(FormatMode::kSFloat, comps[1].mode); - EXPECT_EQ(32U, comps[1].num_bits); - EXPECT_EQ(FormatComponentType::kB, comps[2].type); - EXPECT_EQ(FormatMode::kSFloat, comps[2].mode); - EXPECT_EQ(32U, comps[2].num_bits); + EXPECT_EQ(FormatComponentType::kR, comps[0]->type); + EXPECT_EQ(FormatMode::kSFloat, comps[0]->mode); + EXPECT_EQ(32U, comps[0]->num_bits); + EXPECT_EQ(FormatComponentType::kG, comps[1]->type); + EXPECT_EQ(FormatMode::kSFloat, comps[1]->mode); + EXPECT_EQ(32U, comps[1]->num_bits); + EXPECT_EQ(FormatComponentType::kB, comps[2]->type); + EXPECT_EQ(FormatMode::kSFloat, comps[2]->mode); + EXPECT_EQ(32U, comps[2]->num_bits); } TEST_F(FormatParserTest, GlslStrings) { diff --git a/src/format_test.cc b/src/format_test.cc index 655f3c3..09eb9ae 100644 --- a/src/format_test.cc +++ b/src/format_test.cc @@ -35,19 +35,18 @@ TEST_F(FormatTest, Copy) { EXPECT_TRUE(copy->IsFloat()); EXPECT_EQ(16U, copy->SizeInBytes()); EXPECT_EQ(3U, copy->GetComponents().size()); - EXPECT_TRUE(copy->IsStd140()); EXPECT_EQ(FormatType::kR32G32B32_SFLOAT, copy->GetFormatType()); auto& comp = copy->GetComponents(); - EXPECT_EQ(FormatComponentType::kR, comp[0].type); - EXPECT_EQ(FormatMode::kSFloat, comp[0].mode); - EXPECT_EQ(32U, comp[0].num_bits); - EXPECT_EQ(FormatComponentType::kG, comp[1].type); - EXPECT_EQ(FormatMode::kSFloat, comp[1].mode); - EXPECT_EQ(32U, comp[1].num_bits); - EXPECT_EQ(FormatComponentType::kB, comp[2].type); - EXPECT_EQ(FormatMode::kSFloat, comp[2].mode); - EXPECT_EQ(32U, comp[2].num_bits); + EXPECT_EQ(FormatComponentType::kR, comp[0]->type); + EXPECT_EQ(FormatMode::kSFloat, comp[0]->mode); + EXPECT_EQ(32U, comp[0]->num_bits); + EXPECT_EQ(FormatComponentType::kG, comp[1]->type); + EXPECT_EQ(FormatMode::kSFloat, comp[1]->mode); + EXPECT_EQ(32U, comp[1]->num_bits); + EXPECT_EQ(FormatComponentType::kB, comp[2]->type); + EXPECT_EQ(FormatMode::kSFloat, comp[2]->mode); + EXPECT_EQ(32U, comp[2]->num_bits); } TEST_F(FormatTest, SizeInBytesVector) { @@ -56,9 +55,7 @@ TEST_F(FormatTest, SizeInBytesVector) { ASSERT_TRUE(fmt != nullptr); EXPECT_EQ(3U, fmt->InputNeededPerElement()); - EXPECT_EQ(4U, fmt->ValuesPerElement()); EXPECT_EQ(16U, fmt->SizeInBytes()); - EXPECT_EQ(16U, fmt->SizeInBytesPerRow()); } TEST_F(FormatTest, SizeInBytesMatrix) { @@ -68,10 +65,7 @@ TEST_F(FormatTest, SizeInBytesMatrix) { fmt->SetColumnCount(3); EXPECT_EQ(9U, fmt->InputNeededPerElement()); - EXPECT_EQ(4U, fmt->ValuesPerRow()); - EXPECT_EQ(12U, fmt->ValuesPerElement()); EXPECT_EQ(48U, fmt->SizeInBytes()); - EXPECT_EQ(16U, fmt->SizeInBytesPerRow()); } TEST_F(FormatTest, SizeInBytesMatrixStd140) { @@ -82,7 +76,6 @@ TEST_F(FormatTest, SizeInBytesMatrixStd140) { fmt->SetIsStd140(); EXPECT_EQ(32U, fmt->SizeInBytes()); - EXPECT_EQ(16U, fmt->SizeInBytesPerRow()); } TEST_F(FormatTest, RowCount) { @@ -98,8 +91,6 @@ struct StdData { const char* fmt; uint32_t column_count; bool is_std140; - uint32_t values_per_element; - uint32_t size_in_bytes_per_row; uint32_t size_in_bytes; }; using FormatStdTest = testing::TestWithParam<StdData>; @@ -114,39 +105,33 @@ TEST_P(FormatStdTest, Test) { if (test_data.is_std140) fmt->SetIsStd140(); - EXPECT_EQ(test_data.values_per_element, fmt->ValuesPerElement()) - << test_data.name; EXPECT_EQ(test_data.size_in_bytes, fmt->SizeInBytes()) << test_data.name; - EXPECT_EQ(test_data.size_in_bytes_per_row, fmt->SizeInBytesPerRow()) - << test_data.name; } INSTANTIATE_TEST_SUITE_P( FormatStdTestSamples, FormatStdTest, testing::Values( - StdData{"mat2x2-std140", "R32G32_SFLOAT", 2, true, 8U, 16U, 32U}, - StdData{"mat2x3-std140", "R32G32B32_SFLOAT", 2, true, 8U, 16U, 32U}, - StdData{"mat2x4-std140", "R32G32B32A32_SFLOAT", 2, true, 8U, 16U, 32U}, - StdData{"mat3x2-std140", "R32G32_SFLOAT", 3, true, 12U, 16U, 48U}, - StdData{"mat3x3-std140", "R32G32B32_SFLOAT", 3, true, 12U, 16U, 48U}, - StdData{"mat3x4-std140", "R32G32B32A32_SFLOAT", 3, true, 12U, 16U, 48U}, - StdData{"mat4x2-std140", "R32G32_SFLOAT", 4, true, 16U, 16U, 64U}, - StdData{"mat4x3-std140", "R32G32B32_SFLOAT", 4, true, 16U, 16U, 64U}, - StdData{"mat4x4-std140", "R32G32B32A32_SFLOAT", 4, true, 16U, 16U, 64U}, - StdData{"mat2x2-std430", "R32G32_SFLOAT", 2, false, 4U, 8U, 16U}, - StdData{"mat2x3-std430", "R32G32B32_SFLOAT", 2, false, 8U, 16U, 32U}, - StdData{"mat2x4-std430", "R32G32B32A32_SFLOAT", 2, false, 8U, 16U, 32U}, - StdData{"mat3x2-std430", "R32G32_SFLOAT", 3, false, 6U, 8U, 24U}, - StdData{"mat3x3-std430", "R32G32B32_SFLOAT", 3, false, 12U, 16U, 48U}, - StdData{"mat3x4-std430", "R32G32B32A32_SFLOAT", 3, false, 12U, 16U, - 48U}, - StdData{"mat4x2-std430", "R32G32_SFLOAT", 4, false, 8U, 8U, 32U}, - StdData{"mat4x3-std430", "R32G32B32_SFLOAT", 4, false, 16U, 16U, 64U}, - StdData{"mat4x4-std430", "R32G32B32A32_SFLOAT", 4, false, 16U, 16U, - 64U}, - StdData{"float-std140", "R32_SFLOAT", 1, true, 1U, 4U, 4U}, - StdData{"float-std430", "R32_SFLOAT", 1, false, 1U, 4U, + StdData{"mat2x2-std140", "R32G32_SFLOAT", 2, true, 32U}, + StdData{"mat2x3-std140", "R32G32B32_SFLOAT", 2, true, 32U}, + StdData{"mat2x4-std140", "R32G32B32A32_SFLOAT", 2, true, 32U}, + StdData{"mat3x2-std140", "R32G32_SFLOAT", 3, true, 48U}, + StdData{"mat3x3-std140", "R32G32B32_SFLOAT", 3, true, 48U}, + StdData{"mat3x4-std140", "R32G32B32A32_SFLOAT", 3, true, 48U}, + StdData{"mat4x2-std140", "R32G32_SFLOAT", 4, true, 64U}, + StdData{"mat4x3-std140", "R32G32B32_SFLOAT", 4, true, 64U}, + StdData{"mat4x4-std140", "R32G32B32A32_SFLOAT", 4, true, 64U}, + StdData{"mat2x2-std430", "R32G32_SFLOAT", 2, false, 16U}, + StdData{"mat2x3-std430", "R32G32B32_SFLOAT", 2, false, 32U}, + StdData{"mat2x4-std430", "R32G32B32A32_SFLOAT", 2, false, 32U}, + StdData{"mat3x2-std430", "R32G32_SFLOAT", 3, false, 24U}, + StdData{"mat3x3-std430", "R32G32B32_SFLOAT", 3, false, 48U}, + StdData{"mat3x4-std430", "R32G32B32A32_SFLOAT", 3, false, 48U}, + StdData{"mat4x2-std430", "R32G32_SFLOAT", 4, false, 32U}, + StdData{"mat4x3-std430", "R32G32B32_SFLOAT", 4, false, 64U}, + StdData{"mat4x4-std430", "R32G32B32A32_SFLOAT", 4, false, 64U}, + StdData{"float-std140", "R32_SFLOAT", 1, true, 4U}, + StdData{"float-std430", "R32_SFLOAT", 1, false, 4U})); // NOLINT(whitespace/parens) } // namespace amber diff --git a/src/verifier.cc b/src/verifier.cc index ebabf53..9105482 100644 --- a/src/verifier.cc +++ b/src/verifier.cc @@ -161,95 +161,61 @@ bool IsEqualWithTolerance(const double actual, template <typename T> Result CheckValue(const ProbeSSBOCommand* command, const uint8_t* memory, - const std::vector<Value>& values) { + const Value& value) { const auto comp = command->GetComparator(); const auto& tolerance = command->GetTolerances(); const T* ptr = reinterpret_cast<const T*>(memory); - for (size_t i = 0; i < values.size(); ++i) { - const T val = values[i].IsInteger() ? static_cast<T>(values[i].AsUint64()) - : static_cast<T>(values[i].AsDouble()); - switch (comp) { - case ProbeSSBOCommand::Comparator::kEqual: - if (values[i].IsInteger()) { - if (static_cast<uint64_t>(*ptr) != static_cast<uint64_t>(val)) { - return Result("Line " + std::to_string(command->GetLine()) + - ": Verifier failed: " + std::to_string(*ptr) + - " == " + std::to_string(val) + ", at index " + - std::to_string(i)); - } - } else { - if (!IsEqualWithTolerance(static_cast<const double>(*ptr), - static_cast<const double>(val), kEpsilon)) { - return Result("Line " + std::to_string(command->GetLine()) + - ": Verifier failed: " + std::to_string(*ptr) + - " == " + std::to_string(val) + ", at index " + - std::to_string(i)); - } + const T val = value.IsInteger() ? static_cast<T>(value.AsUint64()) + : static_cast<T>(value.AsDouble()); + switch (comp) { + case ProbeSSBOCommand::Comparator::kEqual: + if (value.IsInteger()) { + if (static_cast<uint64_t>(*ptr) != static_cast<uint64_t>(val)) { + return Result(std::to_string(*ptr) + " == " + std::to_string(val)); } - break; - case ProbeSSBOCommand::Comparator::kNotEqual: - if (values[i].IsInteger()) { - if (static_cast<uint64_t>(*ptr) == static_cast<uint64_t>(val)) { - return Result("Line " + std::to_string(command->GetLine()) + - ": Verifier failed: " + std::to_string(*ptr) + - " != " + std::to_string(val) + ", at index " + - std::to_string(i)); - } - } else { - if (IsEqualWithTolerance(static_cast<const double>(*ptr), - static_cast<const double>(val), kEpsilon)) { - return Result("Line " + std::to_string(command->GetLine()) + - ": Verifier failed: " + std::to_string(*ptr) + - " != " + std::to_string(val) + ", at index " + - std::to_string(i)); - } - } - break; - case ProbeSSBOCommand::Comparator::kFuzzyEqual: - if (!IsEqualWithTolerance( - static_cast<const double>(*ptr), static_cast<const double>(val), - command->HasTolerances() ? tolerance[0].value : kEpsilon, - command->HasTolerances() ? tolerance[0].is_percent : true)) { - return Result("Line " + std::to_string(command->GetLine()) + - ": Verifier failed: " + std::to_string(*ptr) + - " ~= " + std::to_string(val) + ", at index " + - std::to_string(i)); - } - break; - case ProbeSSBOCommand::Comparator::kLess: - if (*ptr >= val) { - return Result("Line " + std::to_string(command->GetLine()) + - ": Verifier failed: " + std::to_string(*ptr) + " < " + - std::to_string(val) + ", at index " + - std::to_string(i)); - } - break; - case ProbeSSBOCommand::Comparator::kLessOrEqual: - if (*ptr > val) { - return Result("Line " + std::to_string(command->GetLine()) + - ": Verifier failed: " + std::to_string(*ptr) + - " <= " + std::to_string(val) + ", at index " + - std::to_string(i)); + } else { + if (!IsEqualWithTolerance(static_cast<const double>(*ptr), + static_cast<const double>(val), kEpsilon)) { + return Result(std::to_string(*ptr) + " == " + std::to_string(val)); } - break; - case ProbeSSBOCommand::Comparator::kGreater: - if (*ptr <= val) { - return Result("Line " + std::to_string(command->GetLine()) + - ": Verifier failed: " + std::to_string(*ptr) + " > " + - std::to_string(val) + ", at index " + - std::to_string(i)); + } + break; + case ProbeSSBOCommand::Comparator::kNotEqual: + if (value.IsInteger()) { + if (static_cast<uint64_t>(*ptr) == static_cast<uint64_t>(val)) { + return Result(std::to_string(*ptr) + " != " + std::to_string(val)); } - break; - case ProbeSSBOCommand::Comparator::kGreaterOrEqual: - if (*ptr < val) { - return Result("Line " + std::to_string(command->GetLine()) + - ": Verifier failed: " + std::to_string(*ptr) + - " >= " + std::to_string(val) + ", at index " + - std::to_string(i)); + } else { + if (IsEqualWithTolerance(static_cast<const double>(*ptr), + static_cast<const double>(val), kEpsilon)) { + return Result(std::to_string(*ptr) + " != " + std::to_string(val)); } - break; - } - ++ptr; + } + break; + case ProbeSSBOCommand::Comparator::kFuzzyEqual: + if (!IsEqualWithTolerance( + static_cast<const double>(*ptr), static_cast<const double>(val), + command->HasTolerances() ? tolerance[0].value : kEpsilon, + command->HasTolerances() ? tolerance[0].is_percent : true)) { + return Result(std::to_string(*ptr) + " ~= " + std::to_string(val)); + } + break; + case ProbeSSBOCommand::Comparator::kLess: + if (*ptr >= val) + return Result(std::to_string(*ptr) + " < " + std::to_string(val)); + break; + case ProbeSSBOCommand::Comparator::kLessOrEqual: + if (*ptr > val) + return Result(std::to_string(*ptr) + " <= " + std::to_string(val)); + break; + case ProbeSSBOCommand::Comparator::kGreater: + if (*ptr <= val) + return Result(std::to_string(*ptr) + " > " + std::to_string(val)); + break; + case ProbeSSBOCommand::Comparator::kGreaterOrEqual: + if (*ptr < val) + return Result(std::to_string(*ptr) + " >= " + std::to_string(val)); + break; } return {}; } @@ -294,34 +260,41 @@ void SetupToleranceForTexels(const ProbeCommand* command, // information given in |framebuffer_format|. std::vector<double> GetActualValuesFromTexel(const uint8_t* texel, const Format* framebuffer_format) { - assert(framebuffer_format && !framebuffer_format->GetComponents().empty()); + assert(framebuffer_format && !framebuffer_format->GetSegments().empty()); - std::vector<double> actual_values(framebuffer_format->GetComponents().size()); + std::vector<double> actual_values(framebuffer_format->GetSegments().size()); uint8_t bit_offset = 0; - for (size_t i = 0; i < framebuffer_format->GetComponents().size(); ++i) { - const auto& component = framebuffer_format->GetComponents()[i]; + for (size_t i = 0; i < framebuffer_format->GetSegments().size(); ++i) { + const auto& seg = framebuffer_format->GetSegments()[i]; + auto component = seg.GetComponent(); + + if (seg.IsPadding()) { + bit_offset += component->num_bits; + continue; + } + uint8_t actual[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - CopyBitsOfMemoryToBuffer(actual, texel, bit_offset, component.num_bits); - if (component.mode == FormatMode::kUFloat || - component.mode == FormatMode::kSFloat) { - if (component.num_bits < 32) { + CopyBitsOfMemoryToBuffer(actual, texel, bit_offset, component->num_bits); + if (component->mode == FormatMode::kUFloat || + component->mode == FormatMode::kSFloat) { + if (component->num_bits < 32) { actual_values[i] = - static_cast<double>(HexFloatToFloat(actual, component.num_bits)); - } else if (component.num_bits == 32) { + static_cast<double>(HexFloatToFloat(actual, component->num_bits)); + } else if (component->num_bits == 32) { float* ptr = reinterpret_cast<float*>(actual); actual_values[i] = static_cast<double>(*ptr); - } else if (component.num_bits == 64) { + } else if (component->num_bits == 64) { double* ptr = reinterpret_cast<double*>(actual); actual_values[i] = *ptr; } else { assert(false && "Bits of component is not for double nor float type"); } } else { - if (component.mode == FormatMode::kSInt || - component.mode == FormatMode::kSNorm) { - switch (component.num_bits) { + if (component->mode == FormatMode::kSInt || + component->mode == FormatMode::kSNorm) { + switch (component->num_bits) { case 8: { int8_t* ptr8 = nullptr; ptr8 = reinterpret_cast<int8_t*>(actual); @@ -351,7 +324,7 @@ std::vector<double> GetActualValuesFromTexel(const uint8_t* texel, } } } else { - switch (component.num_bits) { + switch (component->num_bits) { case 8: { actual_values[i] = static_cast<double>(*actual); break; @@ -381,7 +354,7 @@ std::vector<double> GetActualValuesFromTexel(const uint8_t* texel, } } - bit_offset = static_cast<uint8_t>(bit_offset + component.num_bits); + bit_offset += component->num_bits; } return actual_values; @@ -393,18 +366,22 @@ std::vector<double> GetActualValuesFromTexel(const uint8_t* texel, // ::kUFloat, ::kSFloat. void ScaleTexelValuesIfNeeded(std::vector<double>* texel, const Format* framebuffer_format) { - assert(framebuffer_format->GetComponents().size() == texel->size()); - for (size_t i = 0; i < framebuffer_format->GetComponents().size(); ++i) { - const auto& component = framebuffer_format->GetComponents()[i]; + assert(framebuffer_format->GetSegments().size() == texel->size()); + for (size_t i = 0; i < framebuffer_format->GetSegments().size(); ++i) { + const auto& seg = framebuffer_format->GetSegments()[i]; + if (seg.IsPadding()) + continue; + + auto component = seg.GetComponent(); double scaled_value = (*texel)[i]; - switch (component.mode) { + switch (component->mode) { case FormatMode::kUNorm: - scaled_value /= static_cast<double>((1 << component.num_bits) - 1); + scaled_value /= static_cast<double>((1 << component->num_bits) - 1); break; case FormatMode::kSNorm: scaled_value /= - static_cast<double>((1 << (component.num_bits - 1)) - 1); + static_cast<double>((1 << (component->num_bits - 1)) - 1); break; case FormatMode::kUInt: case FormatMode::kSInt: @@ -412,8 +389,8 @@ void ScaleTexelValuesIfNeeded(std::vector<double>* texel, case FormatMode::kSFloat: break; case FormatMode::kSRGB: - scaled_value /= static_cast<double>((1 << component.num_bits) - 1); - if (component.type != FormatComponentType::kA) + scaled_value /= static_cast<double>((1 << component->num_bits) - 1); + if (component->type != FormatComponentType::kA) scaled_value = SRGBToLinearValue(scaled_value); break; case FormatMode::kUScaled: @@ -437,14 +414,18 @@ bool IsTexelEqualToExpected(const std::vector<double>& texel, const ProbeCommand* command, const double* tolerance, const bool* is_tolerance_percent) { - for (size_t i = 0; i < framebuffer_format->GetComponents().size(); ++i) { - const auto& component = framebuffer_format->GetComponents()[i]; + for (size_t i = 0; i < framebuffer_format->GetSegments().size(); ++i) { + const auto& seg = framebuffer_format->GetSegments()[i]; + if (seg.IsPadding()) + continue; + + auto component = seg.GetComponent(); double texel_for_component = texel[i]; double expected = 0; double current_tolerance = 0; bool is_current_tolerance_percent = false; - switch (component.type) { + switch (component->type) { case FormatComponentType::kA: if (!command->IsRGBA()) { continue; @@ -484,9 +465,13 @@ bool IsTexelEqualToExpected(const std::vector<double>& texel, std::vector<double> GetTexelInRGBA(const std::vector<double>& texel, const Format* framebuffer_format) { std::vector<double> texel_in_rgba(texel.size()); - for (size_t i = 0; i < framebuffer_format->GetComponents().size(); ++i) { - const auto& component = framebuffer_format->GetComponents()[i]; - switch (component.type) { + for (size_t i = 0; i < framebuffer_format->GetSegments().size(); ++i) { + const auto& seg = framebuffer_format->GetSegments()[i]; + if (seg.IsPadding()) + continue; + + auto component = seg.GetComponent(); + switch (component->type) { case FormatComponentType::kR: texel_in_rgba[0] = texel[i]; break; @@ -599,9 +584,9 @@ Result Verifier::Probe(const ProbeCommand* command, if (count_of_invalid_pixels) { const auto& component = framebuffer_format->GetComponents().back(); float scale_factor_for_error_report = 1.0f; - if (component.mode == FormatMode::kUNorm || - component.mode == FormatMode::kSNorm || - component.mode == FormatMode::kSRGB) { + if (component->mode == FormatMode::kUNorm || + component->mode == FormatMode::kSNorm || + component->mode == FormatMode::kSRGB) { scale_factor_for_error_report = 255.0f; } @@ -669,30 +654,59 @@ Result Verifier::ProbeSSBO(const ProbeSSBOCommand* command, std::to_string(fmt->SizeInBytes()) + ")"); } + auto& segments = fmt->GetSegments(); + const uint8_t* ptr = static_cast<const uint8_t*>(buffer) + offset; - if (fmt->IsInt8()) - return CheckValue<int8_t>(command, ptr, values); - if (fmt->IsUint8()) - return CheckValue<uint8_t>(command, ptr, values); - if (fmt->IsInt16()) - return CheckValue<int16_t>(command, ptr, values); - if (fmt->IsUint16()) - return CheckValue<uint16_t>(command, ptr, values); - if (fmt->IsInt32()) - return CheckValue<int32_t>(command, ptr, values); - if (fmt->IsUint32()) - return CheckValue<uint32_t>(command, ptr, values); - if (fmt->IsInt64()) - return CheckValue<int64_t>(command, ptr, values); - if (fmt->IsUint64()) - return CheckValue<uint64_t>(command, ptr, values); - if (fmt->IsFloat()) - return CheckValue<float>(command, ptr, values); - if (fmt->IsDouble()) - return CheckValue<double>(command, ptr, values); - - return Result("Line " + std::to_string(command->GetLine()) + - ": Verifier::ProbeSSBO unknown datum type"); + for (size_t i = 0, k = 0; i < values.size(); ++i, ++k) { + if (k >= segments.size()) + k = 0; + + const auto& value = values[i]; + auto segment = segments[k]; + // Skip over any padding bytes. + while (segment.IsPadding()) { + ptr += segment.GetComponent()->SizeInBytes(); + ++k; + if (k >= segments.size()) + k = 0; + + segment = segments[k]; + } + + Result r; + if (segment.GetComponent()->IsInt8()) + r = CheckValue<int8_t>(command, ptr, value); + else if (segment.GetComponent()->IsUint8()) + r = CheckValue<uint8_t>(command, ptr, value); + else if (segment.GetComponent()->IsInt16()) + r = CheckValue<int16_t>(command, ptr, value); + else if (segment.GetComponent()->IsUint16()) + r = CheckValue<uint16_t>(command, ptr, value); + else if (segment.GetComponent()->IsInt32()) + r = CheckValue<int32_t>(command, ptr, value); + else if (segment.GetComponent()->IsUint32()) + r = CheckValue<uint32_t>(command, ptr, value); + else if (segment.GetComponent()->IsInt64()) + r = CheckValue<int64_t>(command, ptr, value); + else if (segment.GetComponent()->IsUint64()) + r = CheckValue<uint64_t>(command, ptr, value); + else if (segment.GetComponent()->IsFloat()) + r = CheckValue<float>(command, ptr, value); + else if (segment.GetComponent()->IsDouble()) + r = CheckValue<double>(command, ptr, value); + else + return Result("Unknown datum type"); + + if (!r.IsSuccess()) { + return Result("Line " + std::to_string(command->GetLine()) + + ": Verifier failed: " + r.Error() + ", at index " + + std::to_string(i)); + } + + ptr += segment.GetComponent()->SizeInBytes(); + } + + return {}; } } // namespace amber diff --git a/src/verifier_test.cc b/src/verifier_test.cc index 76b454f..21ed101 100644 --- a/src/verifier_test.cc +++ b/src/verifier_test.cc @@ -713,7 +713,7 @@ TEST_F(VerifierTest, ProbeSSBOUint8Single) { Verifier verifier; Result r = verifier.ProbeSSBO(&probe_ssbo, 1, static_cast<const void*>(&ssbo)); - EXPECT_TRUE(r.IsSuccess()); + EXPECT_TRUE(r.IsSuccess()) << r.Error(); } TEST_F(VerifierTest, ProbeSSBOUint8Multiple) { @@ -737,7 +737,7 @@ TEST_F(VerifierTest, ProbeSSBOUint8Multiple) { Verifier verifier; Result r = verifier.ProbeSSBO(&probe_ssbo, 3, ssbo); - EXPECT_TRUE(r.IsSuccess()); + EXPECT_TRUE(r.IsSuccess()) << r.Error(); } TEST_F(VerifierTest, ProbeSSBOUint8Many) { @@ -765,7 +765,7 @@ TEST_F(VerifierTest, ProbeSSBOUint8Many) { Verifier verifier; Result r = verifier.ProbeSSBO(&probe_ssbo, 200, ssbo.data()); - EXPECT_TRUE(r.IsSuccess()); + EXPECT_TRUE(r.IsSuccess()) << r.Error(); } TEST_F(VerifierTest, ProbeSSBOUint32Single) { @@ -788,7 +788,7 @@ TEST_F(VerifierTest, ProbeSSBOUint32Single) { Verifier verifier; Result r = verifier.ProbeSSBO(&probe_ssbo, 1, static_cast<const void*>(&ssbo)); - EXPECT_TRUE(r.IsSuccess()); + EXPECT_TRUE(r.IsSuccess()) << r.Error(); } TEST_F(VerifierTest, ProbeSSBOUint32Multiple) { @@ -813,7 +813,7 @@ TEST_F(VerifierTest, ProbeSSBOUint32Multiple) { Verifier verifier; Result r = verifier.ProbeSSBO(&probe_ssbo, 4, ssbo); - EXPECT_TRUE(r.IsSuccess()); + EXPECT_TRUE(r.IsSuccess()) << r.Error(); } TEST_F(VerifierTest, ProbeSSBOUint32Many) { @@ -841,7 +841,7 @@ TEST_F(VerifierTest, ProbeSSBOUint32Many) { Verifier verifier; Result r = verifier.ProbeSSBO(&probe_ssbo, 200, ssbo.data()); - EXPECT_TRUE(r.IsSuccess()); + EXPECT_TRUE(r.IsSuccess()) << r.Error(); } TEST_F(VerifierTest, ProbeSSBOFloatSingle) { @@ -864,7 +864,7 @@ TEST_F(VerifierTest, ProbeSSBOFloatSingle) { Verifier verifier; Result r = verifier.ProbeSSBO(&probe_ssbo, 1, static_cast<const void*>(&ssbo)); - EXPECT_TRUE(r.IsSuccess()); + EXPECT_TRUE(r.IsSuccess()) << r.Error(); } TEST_F(VerifierTest, ProbeSSBOFloatMultiple) { @@ -889,7 +889,7 @@ TEST_F(VerifierTest, ProbeSSBOFloatMultiple) { Verifier verifier; Result r = verifier.ProbeSSBO(&probe_ssbo, 4, ssbo); - EXPECT_TRUE(r.IsSuccess()); + EXPECT_TRUE(r.IsSuccess()) << r.Error(); } TEST_F(VerifierTest, ProbeSSBOFloatMany) { @@ -917,7 +917,7 @@ TEST_F(VerifierTest, ProbeSSBOFloatMany) { Verifier verifier; Result r = verifier.ProbeSSBO(&probe_ssbo, 200, ssbo.data()); - EXPECT_TRUE(r.IsSuccess()); + EXPECT_TRUE(r.IsSuccess()) << r.Error(); } TEST_F(VerifierTest, ProbeSSBODoubleSingle) { @@ -940,7 +940,7 @@ TEST_F(VerifierTest, ProbeSSBODoubleSingle) { Verifier verifier; Result r = verifier.ProbeSSBO(&probe_ssbo, 1, static_cast<const void*>(&ssbo)); - EXPECT_TRUE(r.IsSuccess()); + EXPECT_TRUE(r.IsSuccess()) << r.Error(); } TEST_F(VerifierTest, ProbeSSBODoubleMultiple) { @@ -965,7 +965,7 @@ TEST_F(VerifierTest, ProbeSSBODoubleMultiple) { Verifier verifier; Result r = verifier.ProbeSSBO(&probe_ssbo, 4, ssbo); - EXPECT_TRUE(r.IsSuccess()); + EXPECT_TRUE(r.IsSuccess()) << r.Error(); } TEST_F(VerifierTest, ProbeSSBODoubleMany) { @@ -993,7 +993,7 @@ TEST_F(VerifierTest, ProbeSSBODoubleMany) { Verifier verifier; Result r = verifier.ProbeSSBO(&probe_ssbo, 200, ssbo.data()); - EXPECT_TRUE(r.IsSuccess()); + EXPECT_TRUE(r.IsSuccess()) << r.Error(); } TEST_F(VerifierTest, ProbeSSBOEqualFail) { @@ -1054,7 +1054,7 @@ TEST_F(VerifierTest, ProbeSSBOFuzzyEqualWithAbsoluteTolerance) { const double ssbo_less[4] = {2.801, 0.631, 9.901, 1234.461}; r = verifier.ProbeSSBO(&probe_ssbo, 4, ssbo_less); - EXPECT_TRUE(r.IsSuccess()); + EXPECT_TRUE(r.IsSuccess()) << r.Error(); } TEST_F(VerifierTest, ProbeSSBOFuzzyEqualWithAbsoluteToleranceFail) { @@ -1114,12 +1114,12 @@ TEST_F(VerifierTest, ProbeSSBOFuzzyEqualWithRelativeTolerance) { Verifier verifier; Result r = verifier.ProbeSSBO(&probe_ssbo, 4, ssbo_more); - EXPECT_TRUE(r.IsSuccess()); + EXPECT_TRUE(r.IsSuccess()) << r.Error(); const double ssbo_less[4] = {2.8972, 0.72928, 9.991, 1233.32545}; r = verifier.ProbeSSBO(&probe_ssbo, sizeof(double) * 4, ssbo_less); - EXPECT_TRUE(r.IsSuccess()); + EXPECT_TRUE(r.IsSuccess()) << r.Error(); } TEST_F(VerifierTest, ProbeSSBOFuzzyEqualWithRelativeToleranceFail) { @@ -1175,7 +1175,7 @@ TEST_F(VerifierTest, ProbeSSBONotEqual) { Verifier verifier; Result r = verifier.ProbeSSBO(&probe_ssbo, 4, ssbo); - EXPECT_TRUE(r.IsSuccess()); + EXPECT_TRUE(r.IsSuccess()) << r.Error(); } TEST_F(VerifierTest, ProbeSSBONotEqualFail) { @@ -1227,7 +1227,7 @@ TEST_F(VerifierTest, ProbeSSBOLess) { Verifier verifier; Result r = verifier.ProbeSSBO(&probe_ssbo, 4, ssbo); - EXPECT_TRUE(r.IsSuccess()); + EXPECT_TRUE(r.IsSuccess()) << r.Error(); } TEST_F(VerifierTest, ProbeSSBOLessFail) { @@ -1279,7 +1279,7 @@ TEST_F(VerifierTest, ProbeSSBOLessOrEqual) { Verifier verifier; Result r = verifier.ProbeSSBO(&probe_ssbo, 4, ssbo); - EXPECT_TRUE(r.IsSuccess()); + EXPECT_TRUE(r.IsSuccess()) << r.Error(); } TEST_F(VerifierTest, ProbeSSBOLessOrEqualFail) { @@ -1331,7 +1331,7 @@ TEST_F(VerifierTest, ProbeSSBOGreater) { Verifier verifier; Result r = verifier.ProbeSSBO(&probe_ssbo, 4, ssbo); - EXPECT_TRUE(r.IsSuccess()); + EXPECT_TRUE(r.IsSuccess()) << r.Error(); } TEST_F(VerifierTest, ProbeSSBOGreaterFail) { @@ -1383,7 +1383,7 @@ TEST_F(VerifierTest, ProbeSSBOGreaterOrEqual) { Verifier verifier; Result r = verifier.ProbeSSBO(&probe_ssbo, sizeof(double) * 4, ssbo); - EXPECT_TRUE(r.IsSuccess()); + EXPECT_TRUE(r.IsSuccess()) << r.Error(); } TEST_F(VerifierTest, ProbeSSBOGreaterOrEqualFail) { @@ -1441,4 +1441,32 @@ TEST_F(VerifierTest, CheckRGBAOrderForFailure) { r.Error()); } +TEST_F(VerifierTest, ProbeSSBOWithPadding) { + Pipeline pipeline(PipelineType::kGraphics); + auto color_buf = pipeline.GenerateDefaultColorAttachmentBuffer(); + + ProbeSSBOCommand probe_ssbo(color_buf.get()); + + FormatParser fp; + probe_ssbo.SetFormat(fp.Parse("float/vec2")); + ASSERT_TRUE(probe_ssbo.GetFormat() != nullptr); + + probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kLessOrEqual); + + std::vector<Value> values; + values.resize(4); + values[0].SetDoubleValue(2.9); + values[1].SetDoubleValue(0.73); + values[2].SetDoubleValue(10.0); + values[3].SetDoubleValue(1234.56); + probe_ssbo.SetValues(std::move(values)); + + // The vec2 will get padded to 4 bytes in std430. + const float ssbo[8] = {1.9f, 0.73f, 0.0f, 0.0f, 9.99f, 1234.560f, 0.0f, 0.0f}; + + Verifier verifier; + Result r = verifier.ProbeSSBO(&probe_ssbo, 4, ssbo); + EXPECT_TRUE(r.IsSuccess()) << r.Error(); +} + } // namespace amber diff --git a/src/vkscript/datum_type_parser.cc b/src/vkscript/datum_type_parser.cc index 223a97d..375421c 100644 --- a/src/vkscript/datum_type_parser.cc +++ b/src/vkscript/datum_type_parser.cc @@ -115,11 +115,11 @@ std::unique_ptr<Format> DatumTypeParser::Parse(const std::string& data) { std::string parts = "ARGB"; const auto& comps = fmt->GetComponents(); for (const auto& comp : comps) { - name += parts[static_cast<uint8_t>(comp.type)] + - std::to_string(comp.num_bits); + name += parts[static_cast<uint8_t>(comp->type)] + + std::to_string(comp->num_bits); } name += "_"; - switch (comps[0].mode) { + switch (comps[0]->mode) { case FormatMode::kUNorm: case FormatMode::kUFloat: case FormatMode::kUScaled: diff --git a/src/vkscript/datum_type_parser_test.cc b/src/vkscript/datum_type_parser_test.cc index 9ba7501..aad4185 100644 --- a/src/vkscript/datum_type_parser_test.cc +++ b/src/vkscript/datum_type_parser_test.cc @@ -22,7 +22,7 @@ namespace { bool AllCompsAreType(Format* fmt, FormatMode mode, uint8_t num_bits) { for (auto& comp : fmt->GetComponents()) { - if (comp.mode != mode || comp.num_bits != num_bits) + if (comp->mode != mode || comp->num_bits != num_bits) return false; } diff --git a/src/vkscript/parser.cc b/src/vkscript/parser.cc index a1c849e..d20136b 100644 --- a/src/vkscript/parser.cc +++ b/src/vkscript/parser.cc @@ -384,19 +384,21 @@ Result Parser::ProcessVertexDataBlock(const SectionParser::Section& section) { v.SetIntValue(token->AsHex()); value_data.push_back(v); } else { - auto& comps = header.format->GetComponents(); - for (size_t i = 0; i < comps.size(); - ++i, token = tokenizer.NextToken()) { + auto& segs = header.format->GetSegments(); + for (const auto& seg : segs) { + if (seg.IsPadding()) + continue; + if (token->IsEOS() || token->IsEOL()) { return Result(make_error(tokenizer, "Too few cells in given vertex data row")); } - auto& comp = comps[i]; + auto comp = seg.GetComponent(); Value v; - if (comp.mode == FormatMode::kUFloat || - comp.mode == FormatMode::kSFloat) { + if (comp->mode == FormatMode::kUFloat || + comp->mode == FormatMode::kSFloat) { Result r = token->ConvertToDouble(); if (!r.IsSuccess()) return r; @@ -410,6 +412,7 @@ Result Parser::ProcessVertexDataBlock(const SectionParser::Section& section) { } value_data.push_back(v); + token = tokenizer.NextToken(); } } } diff --git a/src/vkscript/parser_test.cc b/src/vkscript/parser_test.cc index 29f2ce4..bae2103 100644 --- a/src/vkscript/parser_test.cc +++ b/src/vkscript/parser_test.cc @@ -385,8 +385,8 @@ TEST_F(VkScriptParserTest, VertexDataHeaderGlslString) { auto& comps1 = buffers[1]->GetFormat()->GetComponents(); ASSERT_EQ(2U, comps1.size()); - EXPECT_EQ(FormatMode::kSFloat, comps1[0].mode); - EXPECT_EQ(FormatMode::kSFloat, comps1[1].mode); + EXPECT_EQ(FormatMode::kSFloat, comps1[0]->mode); + EXPECT_EQ(FormatMode::kSFloat, comps1[1]->mode); EXPECT_EQ(static_cast<uint32_t>(0), buffers[1]->ElementCount()); ASSERT_EQ(BufferType::kVertex, buffers[2]->GetBufferType()); @@ -395,9 +395,9 @@ TEST_F(VkScriptParserTest, VertexDataHeaderGlslString) { buffers[2]->GetFormat()->GetFormatType()); auto& comps2 = buffers[2]->GetFormat()->GetComponents(); ASSERT_EQ(3U, comps2.size()); - EXPECT_EQ(FormatMode::kSInt, comps2[0].mode); - EXPECT_EQ(FormatMode::kSInt, comps2[1].mode); - EXPECT_EQ(FormatMode::kSInt, comps2[2].mode); + EXPECT_EQ(FormatMode::kSInt, comps2[0]->mode); + EXPECT_EQ(FormatMode::kSInt, comps2[1]->mode); + EXPECT_EQ(FormatMode::kSInt, comps2[2]->mode); EXPECT_EQ(static_cast<uint32_t>(0), buffers[2]->ElementCount()); } diff --git a/src/vulkan/engine_vulkan.cc b/src/vulkan/engine_vulkan.cc index f8cfb39..73a9391 100644 --- a/src/vulkan/engine_vulkan.cc +++ b/src/vulkan/engine_vulkan.cc @@ -154,12 +154,12 @@ Result EngineVulkan::CreatePipeline(amber::Pipeline* pipeline) { return Result("Vulkan color attachment format is not supported"); } - Format depth_fmt; + Format* depth_fmt = nullptr; if (pipeline->GetDepthBuffer().buffer) { const auto& depth_info = pipeline->GetDepthBuffer(); - depth_fmt = *depth_info.buffer->GetFormat(); - if (!device_->IsFormatSupportedByPhysicalDevice(depth_fmt, + depth_fmt = depth_info.buffer->GetFormat(); + if (!device_->IsFormatSupportedByPhysicalDevice(*depth_fmt, depth_info.buffer)) { return Result("Vulkan depth attachment format is not supported"); } diff --git a/src/vulkan/frame_buffer.cc b/src/vulkan/frame_buffer.cc index 208f6b9..00871f4 100644 --- a/src/vulkan/frame_buffer.cc +++ b/src/vulkan/frame_buffer.cc @@ -44,7 +44,7 @@ FrameBuffer::~FrameBuffer() { } Result FrameBuffer::Initialize(VkRenderPass render_pass, - const Format& depth_format) { + const Format* depth_format) { std::vector<VkImageView> attachments; if (!color_attachments_.empty()) { @@ -75,10 +75,10 @@ Result FrameBuffer::Initialize(VkRenderPass render_pass, } } - if (depth_format.IsFormatKnown()) { + if (depth_format && depth_format->IsFormatKnown()) { depth_image_ = MakeUnique<TransferImage>( - device_, depth_format, - static_cast<VkImageAspectFlags>(depth_format.HasStencilComponent() + device_, *depth_format, + static_cast<VkImageAspectFlags>(depth_format->HasStencilComponent() ? VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT), diff --git a/src/vulkan/frame_buffer.h b/src/vulkan/frame_buffer.h index d5abc55..202726b 100644 --- a/src/vulkan/frame_buffer.h +++ b/src/vulkan/frame_buffer.h @@ -37,7 +37,7 @@ class FrameBuffer { uint32_t height); ~FrameBuffer(); - Result Initialize(VkRenderPass render_pass, const Format& depth_format); + Result Initialize(VkRenderPass render_pass, const Format* depth_format); void ChangeFrameToDrawLayout(CommandBuffer* command); void ChangeFrameToProbeLayout(CommandBuffer* command); diff --git a/src/vulkan/graphics_pipeline.cc b/src/vulkan/graphics_pipeline.cc index 881125e..63881b3 100644 --- a/src/vulkan/graphics_pipeline.cc +++ b/src/vulkan/graphics_pipeline.cc @@ -381,14 +381,16 @@ class RenderPassGuard { GraphicsPipeline::GraphicsPipeline( Device* device, const std::vector<amber::Pipeline::BufferInfo>& color_buffers, - const Format& depth_stencil_format, + Format* depth_stencil_format, uint32_t fence_timeout_ms, const std::vector<VkPipelineShaderStageCreateInfo>& shader_stage_info) : Pipeline(PipelineType::kGraphics, device, fence_timeout_ms, - shader_stage_info), - depth_stencil_format_(depth_stencil_format) { + shader_stage_info) { + if (depth_stencil_format != nullptr) + depth_stencil_format_ = *depth_stencil_format; + for (const auto& info : color_buffers) color_buffers_.push_back(&info); } @@ -694,7 +696,7 @@ Result GraphicsPipeline::Initialize(uint32_t width, return r; frame_ = MakeUnique<FrameBuffer>(device_, color_buffers_, width, height); - r = frame_->Initialize(render_pass_, depth_stencil_format_); + r = frame_->Initialize(render_pass_, &depth_stencil_format_); if (!r.IsSuccess()) return r; diff --git a/src/vulkan/graphics_pipeline.h b/src/vulkan/graphics_pipeline.h index f8be8a7..20f8918 100644 --- a/src/vulkan/graphics_pipeline.h +++ b/src/vulkan/graphics_pipeline.h @@ -42,7 +42,7 @@ class GraphicsPipeline : public Pipeline { GraphicsPipeline( Device* device, const std::vector<amber::Pipeline::BufferInfo>& color_buffers, - const Format& depth_stencil_format, + Format* depth_stencil_format, uint32_t fence_timeout_ms, const std::vector<VkPipelineShaderStageCreateInfo>&); ~GraphicsPipeline() override; |