aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordan sinclair <dsinclair@google.com>2019-09-25 14:36:21 -0400
committerGitHub <noreply@github.com>2019-09-25 14:36:21 -0400
commitcd2efffbe0dffe2bf5ff8c34b6f26b4206a28497 (patch)
tree7377a31cd9eaec4f07f1c7730fd8c767086cfe68
parent3c6db24b40e4bc20df93d2d623ac208d5f94f5f0 (diff)
downloadamber-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.cc10
-rw-r--r--src/amberscript/parser_buffer_test.cc28
-rw-r--r--src/buffer.cc87
-rw-r--r--src/buffer.h4
-rw-r--r--src/buffer_test.cc19
-rw-r--r--src/format.cc107
-rw-r--r--src/format.h55
-rw-r--r--src/format_parser_test.cc24
-rw-r--r--src/format_test.cc73
-rw-r--r--src/verifier.cc290
-rw-r--r--src/verifier_test.cc68
-rw-r--r--src/vkscript/datum_type_parser.cc6
-rw-r--r--src/vkscript/datum_type_parser_test.cc2
-rw-r--r--src/vkscript/parser.cc15
-rw-r--r--src/vkscript/parser_test.cc10
-rw-r--r--src/vulkan/engine_vulkan.cc6
-rw-r--r--src/vulkan/frame_buffer.cc8
-rw-r--r--src/vulkan/frame_buffer.h2
-rw-r--r--src/vulkan/graphics_pipeline.cc10
-rw-r--r--src/vulkan/graphics_pipeline.h2
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;