aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordan sinclair <dsinclair@google.com>2019-10-10 14:13:14 -0400
committerGitHub <noreply@github.com>2019-10-10 14:13:14 -0400
commitbfd82bec68975d552abbbc0f6aa69857d3f53baa (patch)
tree1ff974379c382ae4460fd69884a61fdb90556d64 /src
parentab41eacc3fba9ea3365a57b1712837cb4ed6d2c4 (diff)
downloadamber-bfd82bec68975d552abbbc0f6aa69857d3f53baa.tar.gz
New type structure (#679)
This CL replaces the Format;:Components with a new Type hierarchy in Amber. This allows more flexibility in defining how types are created. Fixes #603
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt6
-rw-r--r--src/amberscript/parser.cc187
-rw-r--r--src/amberscript/parser_buffer_test.cc52
-rw-r--r--src/buffer.cc101
-rw-r--r--src/buffer.h9
-rw-r--r--src/buffer_test.cc56
-rw-r--r--src/format.cc415
-rw-r--r--src/format.h252
-rw-r--r--src/format_data.h4
-rw-r--r--src/format_parser.h54
-rw-r--r--src/format_test.cc1139
-rw-r--r--src/pipeline.cc20
-rw-r--r--src/pipeline.h1
-rw-r--r--src/pipeline_test.cc28
-rw-r--r--src/script.h8
-rw-r--r--src/type.cc101
-rw-r--r--src/type.h298
-rw-r--r--src/type_parser.cc (renamed from src/format_parser.cc)135
-rw-r--r--src/type_parser.h64
-rw-r--r--src/type_parser_test.cc (renamed from src/format_parser_test.cc)120
-rw-r--r--src/type_test.cc399
-rw-r--r--src/verifier.cc260
-rw-r--r--src/verifier_test.cc402
-rw-r--r--src/vkscript/command_parser.cc32
-rw-r--r--src/vkscript/command_parser_test.cc120
-rw-r--r--src/vkscript/datum_type_parser.cc160
-rw-r--r--src/vkscript/datum_type_parser.h4
-rw-r--r--src/vkscript/datum_type_parser_test.cc34
-rw-r--r--src/vkscript/parser.cc55
-rw-r--r--src/vkscript/parser_test.cc12
-rw-r--r--src/vulkan/engine_vulkan.cc10
-rw-r--r--src/vulkan/vertex_buffer_test.cc74
32 files changed, 3432 insertions, 1180 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 76c6f12..1bb94a2 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -22,7 +22,6 @@ set(AMBER_SOURCES
engine.cc
executor.cc
format.cc
- format_parser.cc
parser.cc
pipeline.cc
pipeline_data.cc
@@ -33,6 +32,8 @@ set(AMBER_SOURCES
shader.cc
shader_compiler.cc
tokenizer.cc
+ type.cc
+ type_parser.cc
value.cc
verifier.cc
vkscript/command_parser.cc
@@ -134,13 +135,14 @@ if (${AMBER_ENABLE_TESTS})
command_data_test.cc
descriptor_set_and_binding_parser_test.cc
executor_test.cc
- format_parser_test.cc
format_test.cc
pipeline_test.cc
result_test.cc
script_test.cc
shader_compiler_test.cc
tokenizer_test.cc
+ type_parser_test.cc
+ type_test.cc
verifier_test.cc
vkscript/command_parser_test.cc
vkscript/datum_type_parser_test.cc
diff --git a/src/amberscript/parser.cc b/src/amberscript/parser.cc
index 9c8a300..92cfbfa 100644
--- a/src/amberscript/parser.cc
+++ b/src/amberscript/parser.cc
@@ -20,19 +20,15 @@
#include <utility>
#include <vector>
-#include "src/format_parser.h"
#include "src/make_unique.h"
#include "src/shader_data.h"
#include "src/tokenizer.h"
+#include "src/type_parser.h"
namespace amber {
namespace amberscript {
namespace {
-FormatComponentType FORMAT_TYPES[] = {
- FormatComponentType::kR, FormatComponentType::kG, FormatComponentType::kB,
- FormatComponentType::kA};
-
bool IsComparator(const std::string& in) {
return in == "EQ" || in == "NE" || in == "GT" || in == "LT" || in == "GE" ||
in == "LE";
@@ -54,32 +50,30 @@ ProbeSSBOCommand::Comparator ToComparator(const std::string& in) {
return ProbeSSBOCommand::Comparator::kLessOrEqual;
}
-std::unique_ptr<Format> ToFormat(const std::string& str) {
- std::unique_ptr<Format> fmt;
- bool matrix = false;
-
- FormatParser fp;
- if (str == "int8") {
- fmt = fp.Parse("R8_SINT");
- } else if (str == "int16") {
- fmt = fp.Parse("R16_SINT");
- } else if (str == "int32") {
- fmt = fp.Parse("R32_SINT");
- } else if (str == "int64") {
- fmt = fp.Parse("R64_SINT");
- } else if (str == "uint8") {
- fmt = fp.Parse("R8_UINT");
- } else if (str == "uint16") {
- fmt = fp.Parse("R16_UINT");
- } else if (str == "uint32") {
- fmt = fp.Parse("R32_UINT");
- } else if (str == "uint64") {
- fmt = fp.Parse("R64_UINT");
- } else if (str == "float") {
- fmt = fp.Parse("R32_SFLOAT");
- } else if (str == "double") {
- fmt = fp.Parse("R64_SFLOAT");
- } else if (str.length() > 7 && str.substr(0, 3) == "vec") {
+std::unique_ptr<type::Type> ToType(const std::string& str) {
+ TypeParser parser;
+ if (str == "int8")
+ return parser.Parse("R8_SINT");
+ if (str == "int16")
+ return parser.Parse("R16_SINT");
+ if (str == "int32")
+ return parser.Parse("R32_SINT");
+ if (str == "int64")
+ return parser.Parse("R64_SINT");
+ if (str == "uint8")
+ return parser.Parse("R8_UINT");
+ if (str == "uint16")
+ return parser.Parse("R16_UINT");
+ if (str == "uint32")
+ return parser.Parse("R32_UINT");
+ if (str == "uint64")
+ return parser.Parse("R64_UINT");
+ if (str == "float")
+ return parser.Parse("R32_SFLOAT");
+ if (str == "double")
+ return parser.Parse("R64_SFLOAT");
+
+ if (str.length() > 7 && str.substr(0, 3) == "vec") {
if (str[4] != '<' || str[str.length() - 1] != '>')
return nullptr;
@@ -87,25 +81,23 @@ std::unique_ptr<Format> ToFormat(const std::string& str) {
if (component_count < 2 || component_count > 4)
return nullptr;
- auto sub_fmt = ToFormat(str.substr(5, str.length() - 6));
- if (!sub_fmt)
+ auto type = ToType(str.substr(5, str.length() - 6));
+ if (!type)
return nullptr;
- if (sub_fmt->RowCount() != 1 || sub_fmt->ColumnCount() != 1)
+ if (!type->IsNumber() || type->IsArray() || type->IsVec() ||
+ type->IsMatrix()) {
return nullptr;
+ }
- fmt = MakeUnique<Format>();
- const auto* comp = sub_fmt->GetOnlyComponent();
- // TODO(dsinclair): Make sure this isn't a struct.
- for (int i = 0; i < component_count; ++i)
- fmt->AddComponent(FORMAT_TYPES[i], comp->mode, comp->num_bits);
+ type->SetRowCount(static_cast<uint32_t>(component_count));
+ return type;
+ }
- } else if (str.length() > 9 && str.substr(0, 3) == "mat") {
+ if (str.length() > 9 && str.substr(0, 3) == "mat") {
if (str[4] != 'x' || str[6] != '<' || str[str.length() - 1] != '>')
return nullptr;
- matrix = true;
-
int column_count = str[3] - '0';
if (column_count < 2 || column_count > 4)
return nullptr;
@@ -114,38 +106,19 @@ std::unique_ptr<Format> ToFormat(const std::string& str) {
if (row_count < 2 || row_count > 4)
return nullptr;
- auto sub_fmt = ToFormat(str.substr(7, str.length() - 8));
- if (!sub_fmt)
+ auto type = ToType(str.substr(7, str.length() - 8));
+ if (!type)
return nullptr;
-
- if (sub_fmt->RowCount() != 1 || sub_fmt->ColumnCount() != 1)
- return nullptr;
-
- fmt = MakeUnique<Format>();
- fmt->SetColumnCount(static_cast<uint32_t>(column_count));
-
- const auto* comp = sub_fmt->GetOnlyComponent();
- // TODO(dsinclair): Make sure this isn't a struct.
- for (int i = 0; i < row_count; ++i)
- fmt->AddComponent(FORMAT_TYPES[i], comp->mode, comp->num_bits);
-
- } else {
- return nullptr;
- }
-
- // Convert the name back into a FormatType so we can use it in the buffer
- // later Otherwise, we end up with a type of Unknown.
- //
- // There is no equivalent type for a matrix.
- if (!matrix) {
- std::string name = fmt->GenerateName();
- if (name == "")
+ if (!type->IsNumber() || type->IsArray() || type->IsVec() ||
+ type->IsMatrix()) {
return nullptr;
+ }
- fmt->SetFormatType(FormatParser::NameToType(name));
+ type->SetRowCount(static_cast<uint32_t>(row_count));
+ type->SetColumnCount(static_cast<uint32_t>(column_count));
+ return type;
}
-
- return fmt;
+ return nullptr;
}
} // namespace
@@ -206,10 +179,10 @@ Result Parser::Parse(const std::string& data) {
if (pipeline->GetColorAttachments().empty()) {
auto* buf = script_->GetBuffer(Pipeline::kGeneratedColorBuffer);
if (!buf) {
- auto new_buf = pipeline->GenerateDefaultColorAttachmentBuffer();
- buf = new_buf.get();
+ auto color_buf = pipeline->GenerateDefaultColorAttachmentBuffer();
+ buf = color_buf.get();
- Result r = script_->AddBuffer(std::move(new_buf));
+ Result r = script_->AddBuffer(std::move(color_buf));
if (!r.IsSuccess())
return r;
}
@@ -546,15 +519,20 @@ Result Parser::ParseShaderSpecialization(Pipeline* pipeline) {
if (!token->IsString())
return Result("expected data type in SPECIALIZE subcommand");
- auto fmt = ToFormat(token->AsString());
- if (!fmt)
+ auto type = ToType(token->AsString());
+ if (!type)
return Result("invalid data_type provided");
+ if (!type->IsNumber())
+ return Result("only numeric types are accepted for specialization values");
+
+ auto num = type->AsNumber();
token = tokenizer_->NextToken();
uint32_t value = 0;
- if (fmt->IsUint32() || fmt->IsInt32()) {
+ if (type::Type::IsUint32(num->GetFormatMode(), num->NumBits()) ||
+ type::Type::IsInt32(num->GetFormatMode(), num->NumBits())) {
value = token->AsUint32();
- } else if (fmt->IsFloat()) {
+ } else if (type::Type::IsFloat32(num->GetFormatMode(), num->NumBits())) {
Result r = token->ConvertToDouble();
if (!r.IsSuccess())
return Result("value is not a floating point value");
@@ -870,16 +848,17 @@ Result Parser::ParsePipelineSet(Pipeline* pipeline) {
if (!token->IsString())
return Result("expected data type");
- auto fmt = ToFormat(token->AsString());
- if (!fmt)
+ auto type = ToType(token->AsString());
+ if (!type)
return Result("invalid data_type provided");
token = tokenizer_->NextToken();
if (!token->IsInteger() && !token->IsDouble())
return Result("expected data value");
+ auto fmt = MakeUnique<Format>(type.get());
Value value;
- if (fmt->IsFloat() || fmt->IsDouble())
+ if (fmt->IsFloat32() || fmt->IsFloat64())
value.SetDoubleValue(token->AsDouble());
else
value.SetIntValue(token->AsUint64());
@@ -891,6 +870,7 @@ Result Parser::ParsePipelineSet(Pipeline* pipeline) {
info.value = value;
pipeline->SetArg(std::move(info));
script_->RegisterFormat(std::move(fmt));
+ script_->RegisterType(std::move(type));
return ValidateEndOfStatement("SET command");
}
@@ -923,13 +903,15 @@ Result Parser::ParseBuffer() {
buffer = MakeUnique<Buffer>();
- FormatParser fmt_parser;
- auto fmt = fmt_parser.Parse(token->AsString());
- if (fmt == nullptr)
+ TypeParser type_parser;
+ auto type = type_parser.Parse(token->AsString());
+ if (type == nullptr)
return Result("invalid BUFFER FORMAT");
+ auto fmt = MakeUnique<Format>(type.get());
buffer->SetFormat(fmt.get());
script_->RegisterFormat(std::move(fmt));
+ script_->RegisterType(std::move(type));
} else {
return Result("unknown BUFFER command provided: " + cmd);
}
@@ -947,18 +929,22 @@ Result Parser::ParseBufferInitializer(Buffer* buffer) {
if (!token->IsString())
return Result("BUFFER invalid data type");
- FormatParser fp;
- auto fmt = fp.Parse(token->AsString());
- if (fmt != nullptr) {
+ TypeParser parser;
+ auto type = parser.Parse(token->AsString());
+ std::unique_ptr<Format> fmt;
+ if (type != nullptr) {
+ fmt = MakeUnique<Format>(type.get());
buffer->SetFormat(fmt.get());
} else {
- fmt = ToFormat(token->AsString());
- if (!fmt)
+ type = ToType(token->AsString());
+ if (!type)
return Result("invalid data_type provided");
+ fmt = MakeUnique<Format>(type.get());
buffer->SetFormat(fmt.get());
}
script_->RegisterFormat(std::move(fmt));
+ script_->RegisterType(std::move(type));
token = tokenizer_->NextToken();
if (!token->IsString())
@@ -1014,7 +1000,7 @@ Result Parser::ParseBufferInitializerFill(Buffer* buffer,
return Result("invalid BUFFER fill value");
auto fmt = buffer->GetFormat();
- bool is_double_data = fmt->IsFloat() || fmt->IsDouble();
+ bool is_double_data = fmt->IsFloat32() || fmt->IsFloat64();
// Inflate the size because our items are multi-dimensional.
size_in_items = size_in_items * fmt->InputNeededPerElement();
@@ -1042,17 +1028,21 @@ Result Parser::ParseBufferInitializerSeries(Buffer* buffer,
if (!token->IsInteger() && !token->IsDouble())
return Result("invalid BUFFER series_from value");
- auto fmt = buffer->GetFormat();
- if (fmt->RowCount() > 1 || fmt->ColumnCount() > 1)
+ auto type = buffer->GetFormat()->GetType();
+ if (type->IsMatrix() || type->IsVec())
return Result("BUFFER series_from must not be multi-row/column types");
- bool is_double_data = fmt->IsFloat() || fmt->IsDouble();
-
Value counter;
- if (is_double_data)
+
+ auto n = type->AsNumber();
+ FormatMode mode = n->GetFormatMode();
+ uint32_t num_bits = n->NumBits();
+ if (type::Type::IsFloat32(mode, num_bits) ||
+ type::Type::IsFloat64(mode, num_bits)) {
counter.SetDoubleValue(token->AsDouble());
- else
+ } else {
counter.SetIntValue(token->AsUint64());
+ }
token = tokenizer_->NextToken();
if (!token->IsString())
@@ -1069,7 +1059,8 @@ Result Parser::ParseBufferInitializerSeries(Buffer* buffer,
std::vector<Value> values;
values.resize(size_in_items);
for (size_t i = 0; i < size_in_items; ++i) {
- if (is_double_data) {
+ if (type::Type::IsFloat32(mode, num_bits) ||
+ type::Type::IsFloat64(mode, num_bits)) {
double value = counter.AsDouble();
values[i].SetDoubleValue(value);
counter.SetDoubleValue(value + token->AsDouble());
@@ -1088,7 +1079,7 @@ Result Parser::ParseBufferInitializerSeries(Buffer* buffer,
Result Parser::ParseBufferInitializerData(Buffer* buffer) {
auto fmt = buffer->GetFormat();
- bool is_double_type = fmt->IsFloat() || fmt->IsDouble();
+ bool is_double_type = fmt->IsFloat32() || fmt->IsFloat64();
std::vector<Value> values;
for (auto token = tokenizer_->NextToken();; token = tokenizer_->NextToken()) {
@@ -1358,7 +1349,7 @@ Result Parser::ParseValues(const std::string& name,
while (!token->IsEOL() && !token->IsEOS()) {
Value v;
- if (fmt->IsFloat() || fmt->IsDouble()) {
+ if (fmt->IsFloat32() || fmt->IsFloat64()) {
if (!token->IsInteger() && !token->IsDouble()) {
return Result(std::string("Invalid value provided to ") + name +
" command: " + token->ToOriginalString());
diff --git a/src/amberscript/parser_buffer_test.cc b/src/amberscript/parser_buffer_test.cc
index 1826af5..a0aa357 100644
--- a/src/amberscript/parser_buffer_test.cc
+++ b/src/amberscript/parser_buffer_test.cc
@@ -105,7 +105,7 @@ END)";
EXPECT_EQ("my_buffer", buffers[0]->GetName());
auto* buffer = buffers[0].get();
- EXPECT_TRUE(buffer->GetFormat()->IsFloat());
+ EXPECT_TRUE(buffer->GetFormat()->IsFloat32());
EXPECT_EQ(Format::Layout::kStd430, buffer->GetFormat()->GetLayout());
EXPECT_EQ(1U, buffer->ElementCount());
EXPECT_EQ(4U, buffer->ValueCount());
@@ -138,15 +138,14 @@ END)";
EXPECT_EQ("my_buffer", buffers[0]->GetName());
auto* buffer = buffers[0].get();
- EXPECT_TRUE(buffer->GetFormat()->IsFloat());
+ EXPECT_TRUE(buffer->GetFormat()->IsFloat32());
EXPECT_EQ(Format::Layout::kStd140, buffer->GetFormat()->GetLayout());
EXPECT_EQ(1U, buffer->ElementCount());
- EXPECT_EQ(8U, buffer->ValueCount());
+ EXPECT_EQ(4U, buffer->ValueCount());
EXPECT_EQ(8U * sizeof(float), buffer->GetSizeInBytes());
std::vector<float> results = {1.f, 2.f, 0.f, 0.f, 3.f, 4.f, 0.f, 0.f};
const auto* data = buffer->GetValues<float>();
- ASSERT_EQ(results.size(), buffer->ValueCount());
for (size_t i = 0; i < results.size(); ++i) {
EXPECT_FLOAT_EQ(results[i], data[i]);
}
@@ -229,7 +228,7 @@ TEST_F(AmberScriptParserTest, BufferDataFloat) {
EXPECT_EQ("my_buffer", buffers[0]->GetName());
auto* buffer = buffers[0].get();
- EXPECT_TRUE(buffer->GetFormat()->IsFloat());
+ EXPECT_TRUE(buffer->GetFormat()->IsFloat32());
EXPECT_EQ(Format::Layout::kStd430, buffer->GetFormat()->GetLayout());
EXPECT_EQ(4U, buffer->ElementCount());
EXPECT_EQ(4U, buffer->ValueCount());
@@ -287,7 +286,7 @@ TEST_F(AmberScriptParserTest, BufferFillFloat) {
auto* buffer = buffers[0].get();
EXPECT_EQ("my_buffer", buffer->GetName());
- EXPECT_TRUE(buffer->GetFormat()->IsFloat());
+ EXPECT_TRUE(buffer->GetFormat()->IsFloat32());
EXPECT_EQ(Format::Layout::kStd430, buffer->GetFormat()->GetLayout());
EXPECT_EQ(5U, buffer->ElementCount());
EXPECT_EQ(5U, buffer->ValueCount());
@@ -348,7 +347,7 @@ TEST_F(AmberScriptParserTest, BufferSeriesFloat) {
auto* buffer = buffers[0].get();
EXPECT_EQ("my_buffer", buffer->GetName());
- EXPECT_TRUE(buffer->GetFormat()->IsFloat());
+ EXPECT_TRUE(buffer->GetFormat()->IsFloat32());
EXPECT_EQ(Format::Layout::kStd430, buffer->GetFormat()->GetLayout());
EXPECT_EQ(5U, buffer->ElementCount());
EXPECT_EQ(5U, buffer->ValueCount());
@@ -564,21 +563,15 @@ TEST_F(AmberScriptParserTest, BufferFormat) {
EXPECT_EQ("my_buf", buffer->GetName());
auto fmt = buffer->GetFormat();
+ EXPECT_EQ(FormatType::kR32G32B32A32_SINT, fmt->GetFormatType());
auto& segs = fmt->GetSegments();
ASSERT_EQ(4U, segs.size());
- EXPECT_EQ(FormatComponentType::kR, segs[0].GetComponent()->type);
- EXPECT_EQ(FormatMode::kSInt, segs[0].GetComponent()->mode);
- EXPECT_EQ(32U, segs[0].GetComponent()->num_bits);
- EXPECT_EQ(FormatComponentType::kG, segs[1].GetComponent()->type);
- EXPECT_EQ(FormatMode::kSInt, segs[1].GetComponent()->mode);
- EXPECT_EQ(32U, segs[1].GetComponent()->num_bits);
- EXPECT_EQ(FormatComponentType::kB, segs[2].GetComponent()->type);
- EXPECT_EQ(FormatMode::kSInt, segs[2].GetComponent()->mode);
- EXPECT_EQ(32U, segs[2].GetComponent()->num_bits);
- EXPECT_EQ(FormatComponentType::kA, segs[3].GetComponent()->type);
- EXPECT_EQ(FormatMode::kSInt, segs[3].GetComponent()->mode);
- EXPECT_EQ(32U, segs[3].GetComponent()->num_bits);
+ for (size_t i = 0; i < 4; ++i) {
+ EXPECT_EQ(segs[i].GetNumBits(), 32);
+ EXPECT_EQ(segs[i].GetFormatMode(), FormatMode::kSInt);
+ EXPECT_EQ(segs[i].GetName(), static_cast<FormatComponentType>(i));
+ }
}
struct BufferParseError {
@@ -697,12 +690,11 @@ TEST_P(AmberScriptParserBufferDataTypeTest, BufferTypes) {
auto* buffer = buffers[0].get();
auto fmt = buffer->GetFormat();
- EXPECT_EQ(test_data.row_count, fmt->RowCount());
- EXPECT_EQ(test_data.column_count, fmt->ColumnCount());
+ EXPECT_EQ(test_data.row_count, fmt->GetType()->RowCount());
+ EXPECT_EQ(test_data.column_count, fmt->GetType()->ColumnCount());
- auto comp = fmt->GetSegments()[0].GetComponent();
- EXPECT_EQ(test_data.type, comp->mode);
- EXPECT_EQ(test_data.num_bits, comp->num_bits);
+ EXPECT_EQ(test_data.type, fmt->GetSegments()[0].GetFormatMode());
+ EXPECT_EQ(test_data.num_bits, fmt->GetSegments()[0].GetNumBits());
}
INSTANTIATE_TEST_SUITE_P(
AmberScriptParserTestsDataType,
@@ -715,16 +707,16 @@ INSTANTIATE_TEST_SUITE_P(
BufferData{"uint16", FormatMode::kUInt, 16, 1, 1},
BufferData{"uint32", FormatMode::kUInt, 32, 1, 1},
BufferData{"uint64", FormatMode::kUInt, 64, 1, 1},
- BufferData{"float", FormatMode::kSFloat, 32, 1, 1},
- BufferData{"double", FormatMode::kSFloat, 64, 1, 1},
BufferData{"vec2<int8>", FormatMode::kSInt, 8, 2, 1},
- BufferData{"vec3<float>", FormatMode::kSFloat, 32, 3, 1},
BufferData{"vec4<uint32>", FormatMode::kUInt, 32, 4, 1},
BufferData{"mat2x4<int32>", FormatMode::kSInt, 32, 4, 2},
- BufferData{"mat3x3<float>", FormatMode::kSFloat, 32, 3, 3},
BufferData{"mat4x2<uint16>", FormatMode::kUInt, 16, 2, 4},
- BufferData{"B8G8R8_UNORM", FormatMode::kUNorm, 8, 3,
- 1})); // NOLINT(whitespace/parens)
+ BufferData{"B8G8R8_UNORM", FormatMode::kUNorm, 8, 3, 1},
+ BufferData{"float", FormatMode::kSFloat, 32, 1, 1},
+ BufferData{"double", FormatMode::kSFloat, 64, 1, 1},
+ BufferData{"vec3<float>", FormatMode::kSFloat, 32, 3, 1},
+ BufferData{"mat3x3<float>", FormatMode::kSFloat, 32, 3,
+ 3})); // NOLINT(whitespace/parens)
struct NameData {
const char* name;
diff --git a/src/buffer.cc b/src/buffer.cc
index 5a42508..c8b8f96 100644
--- a/src/buffer.cc
+++ b/src/buffer.cc
@@ -60,33 +60,35 @@ 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::Segment* seg,
const uint8_t* buf1,
const uint8_t* buf2) {
- if (comp->IsInt8())
+ FormatMode mode = seg->GetFormatMode();
+ uint32_t num_bits = seg->GetNumBits();
+ if (type::Type::IsInt8(mode, num_bits))
return Sub<int8_t>(buf1, buf2);
- if (comp->IsInt16())
+ if (type::Type::IsInt16(mode, num_bits))
return Sub<int16_t>(buf1, buf2);
- if (comp->IsInt32())
+ if (type::Type::IsInt32(mode, num_bits))
return Sub<int32_t>(buf1, buf2);
- if (comp->IsInt64())
+ if (type::Type::IsInt64(mode, num_bits))
return Sub<int64_t>(buf1, buf2);
- if (comp->IsUint8())
+ if (type::Type::IsUint8(mode, num_bits))
return Sub<uint8_t>(buf1, buf2);
- if (comp->IsUint16())
+ if (type::Type::IsUint16(mode, num_bits))
return Sub<uint16_t>(buf1, buf2);
- if (comp->IsUint32())
+ if (type::Type::IsUint32(mode, num_bits))
return Sub<uint32_t>(buf1, buf2);
- if (comp->IsUint64())
+ if (type::Type::IsUint64(mode, num_bits))
return Sub<uint64_t>(buf1, buf2);
// TOOD(dsinclair): Handle float16 ...
- if (comp->IsFloat16()) {
+ if (type::Type::IsFloat16(mode, num_bits)) {
assert(false && "Float16 suppport not implemented");
return 0.0;
}
- if (comp->IsFloat())
+ if (type::Type::IsFloat32(mode, num_bits))
return Sub<float>(buf1, buf2);
- if (comp->IsDouble())
+ if (type::Type::IsFloat64(mode, num_bits))
return Sub<double>(buf1, buf2);
assert(false && "NOTREACHED");
@@ -159,12 +161,16 @@ std::vector<double> Buffer::CalculateDiffs(const Buffer* buffer) const {
const auto& segments = format_->GetSegments();
for (size_t i = 0; i < ElementCount(); ++i) {
for (const auto& seg : segments) {
- if (!seg.IsPadding())
- diffs.push_back(
- CalculateDiff(seg.GetComponent(), buf_1_ptr, buf_2_ptr));
+ if (seg.IsPadding()) {
+ buf_1_ptr += seg.PaddingBytes();
+ buf_2_ptr += seg.PaddingBytes();
+ continue;
+ }
+
+ diffs.push_back(CalculateDiff(&seg, buf_1_ptr, buf_2_ptr));
- buf_1_ptr += seg.GetComponent()->SizeInBytes();
- buf_2_ptr += seg.GetComponent()->SizeInBytes();
+ buf_1_ptr += seg.SizeInBytes();
+ buf_2_ptr += seg.SizeInBytes();
}
}
@@ -210,7 +216,7 @@ Result Buffer::RecalculateMaxSizeInBytes(const std::vector<Value>& data,
((offset / format_->SizeInBytes()) * format_->InputNeededPerElement()) +
static_cast<uint32_t>(data.size());
uint32_t element_count = value_count;
- if (format_->GetPackSize() == 0) {
+ if (!format_->IsPacked()) {
// This divides by the needed input values, not the values per element.
// The assumption being the values coming in are read from the input,
// where components are specified. The needed values maybe less then the
@@ -229,6 +235,7 @@ Result Buffer::SetDataWithOffset(const std::vector<Value>& data,
uint32_t value_count =
((offset / format_->SizeInBytes()) * format_->InputNeededPerElement()) +
static_cast<uint32_t>(data.size());
+
// The buffer should only be resized to become bigger. This means that if a
// command was run to set the buffer size we'll honour that size until a
// request happens to make the buffer bigger.
@@ -254,82 +261,68 @@ Result Buffer::SetDataWithOffset(const std::vector<Value>& data,
uint8_t* ptr = bytes_.data() + offset;
const auto& segments = format_->GetSegments();
for (uint32_t i = 0; i < data.size();) {
- const auto pack_size = format_->GetPackSize();
- if (pack_size) {
- if (pack_size == 8) {
- *(ValuesAs<uint8_t>(ptr)) = data[i].AsUint8();
- ptr += sizeof(uint8_t);
- } else if (pack_size == 16) {
- *(ValuesAs<uint16_t>(ptr)) = data[i].AsUint16();
- ptr += sizeof(uint16_t);
- } else if (pack_size == 32) {
- *(ValuesAs<uint32_t>(ptr)) = data[i].AsUint32();
- ptr += sizeof(uint32_t);
- }
- ++i;
- continue;
- }
-
for (const auto& seg : segments) {
- Value v;
- if (!seg.IsPadding()) {
- v = data[i];
- ++i;
+ if (seg.IsPadding()) {
+ ptr += seg.PaddingBytes();
+ continue;
}
- ptr += WriteValueFromComponent(v, seg.GetComponent(), ptr);
+ Value v = data[i++];
+ ptr += WriteValueFromComponent(v, seg.GetFormatMode(), seg.GetNumBits(),
+ ptr);
}
}
return {};
}
uint32_t Buffer::WriteValueFromComponent(const Value& value,
- const Format::Component* comp,
+ FormatMode mode,
+ uint32_t num_bits,
uint8_t* ptr) {
- if (comp->IsInt8()) {
+ if (type::Type::IsInt8(mode, num_bits)) {
*(ValuesAs<int8_t>(ptr)) = value.AsInt8();
return sizeof(int8_t);
}
- if (comp->IsInt16()) {
+ if (type::Type::IsInt16(mode, num_bits)) {
*(ValuesAs<int16_t>(ptr)) = value.AsInt16();
return sizeof(int16_t);
}
- if (comp->IsInt32()) {
+ if (type::Type::IsInt32(mode, num_bits)) {
*(ValuesAs<int32_t>(ptr)) = value.AsInt32();
return sizeof(int32_t);
}
- if (comp->IsInt64()) {
+ if (type::Type::IsInt64(mode, num_bits)) {
*(ValuesAs<int64_t>(ptr)) = value.AsInt64();
return sizeof(int64_t);
}
- if (comp->IsUint8()) {
+ if (type::Type::IsUint8(mode, num_bits)) {
*(ValuesAs<uint8_t>(ptr)) = value.AsUint8();
return sizeof(uint8_t);
}
- if (comp->IsUint16()) {
+ if (type::Type::IsUint16(mode, num_bits)) {
*(ValuesAs<uint16_t>(ptr)) = value.AsUint16();
return sizeof(uint16_t);
}
- if (comp->IsUint32()) {
+ if (type::Type::IsUint32(mode, num_bits)) {
*(ValuesAs<uint32_t>(ptr)) = value.AsUint32();
return sizeof(uint32_t);
}
- if (comp->IsUint64()) {
+ if (type::Type::IsUint64(mode, num_bits)) {
*(ValuesAs<uint64_t>(ptr)) = value.AsUint64();
return sizeof(uint64_t);
}
- if (comp->IsFloat()) {
+ if (type::Type::IsFloat16(mode, num_bits)) {
+ *(ValuesAs<uint16_t>(ptr)) = FloatToHexFloat16(value.AsFloat());
+ return sizeof(uint16_t);
+ }
+ if (type::Type::IsFloat32(mode, num_bits)) {
*(ValuesAs<float>(ptr)) = value.AsFloat();
return sizeof(float);
}
- if (comp->IsDouble()) {
+ if (type::Type::IsFloat64(mode, num_bits)) {
*(ValuesAs<double>(ptr)) = value.AsDouble();
return sizeof(double);
}
- if (comp->IsFloat16()) {
- *(ValuesAs<uint16_t>(ptr)) = FloatToHexFloat16(value.AsFloat());
- return sizeof(uint16_t);
- }
// The float 10 and float 11 sizes are only used in PACKED formats.
assert(false && "Not reached");
diff --git a/src/buffer.h b/src/buffer.h
index 813b6aa..7eec699 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -108,7 +108,7 @@ class Buffer {
element_count_ = 0;
return;
}
- if (format_->GetPackSize() > 0) {
+ if (format_->IsPacked()) {
element_count_ = count;
} else {
// This divides by the needed input values, not the values per element.
@@ -123,9 +123,9 @@ class Buffer {
if (!format_)
return 0;
// Packed formats are single values.
- if (format_->GetPackSize() > 0)
+ if (format_->IsPacked())
return element_count_;
- return element_count_ * format_->ValuesPerElement();
+ return element_count_ * format_->InputNeededPerElement();
}
/// Returns the number of bytes needed for the data in the buffer.
@@ -198,7 +198,8 @@ class Buffer {
private:
uint32_t WriteValueFromComponent(const Value& value,
- const Format::Component* comp,
+ FormatMode mode,
+ uint32_t num_bits,
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 5c52c0f..a869f7e 100644
--- a/src/buffer_test.cc
+++ b/src/buffer_test.cc
@@ -17,7 +17,7 @@
#include <utility>
#include "gtest/gtest.h"
-#include "src/format_parser.h"
+#include "src/type_parser.h"
namespace amber {
@@ -31,11 +31,12 @@ TEST_F(BufferTest, EmptyByDefault) {
}
TEST_F(BufferTest, Size) {
- FormatParser fp;
- auto fmt = fp.Parse("R16_SINT");
+ TypeParser parser;
+ auto type = parser.Parse("R16_SINT");
+ Format fmt(type.get());
Buffer b(BufferType::kColor);
- b.SetFormat(fmt.get());
+ b.SetFormat(&fmt);
b.SetElementCount(10);
EXPECT_EQ(10, b.ElementCount());
EXPECT_EQ(10, b.ValueCount());
@@ -46,11 +47,12 @@ TEST_F(BufferTest, SizeFromData) {
std::vector<Value> values;
values.resize(5);
- FormatParser fp;
- auto fmt = fp.Parse("R32_SFLOAT");
+ TypeParser parser;
+ auto type = parser.Parse("R32_SFLOAT");
+ Format fmt(type.get());
Buffer b(BufferType::kColor);
- b.SetFormat(fmt.get());
+ b.SetFormat(&fmt);
b.SetData(std::move(values));
EXPECT_EQ(5, b.ElementCount());
@@ -62,11 +64,12 @@ TEST_F(BufferTest, SizeFromDataDoesNotOverrideSize) {
std::vector<Value> values;
values.resize(5);
- FormatParser fp;
- auto fmt = fp.Parse("R32_SFLOAT");
+ TypeParser parser;
+ auto type = parser.Parse("R32_SFLOAT");
+ Format fmt(type.get());
Buffer b(BufferType::kColor);
- b.SetFormat(fmt.get());
+ b.SetFormat(&fmt);
b.SetElementCount(20);
b.SetData(std::move(values));
@@ -76,12 +79,13 @@ TEST_F(BufferTest, SizeFromDataDoesNotOverrideSize) {
}
TEST_F(BufferTest, SizeMatrixStd430) {
- FormatParser fp;
- auto fmt = fp.Parse("R16G16_SINT");
- fmt->SetColumnCount(3);
+ TypeParser parser;
+ auto type = parser.Parse("R16G16_SINT");
+ type->SetColumnCount(3);
+ Format fmt(type.get());
Buffer b(BufferType::kColor);
- b.SetFormat(fmt.get());
+ b.SetFormat(&fmt);
b.SetElementCount(10);
EXPECT_EQ(10, b.ElementCount());
@@ -90,31 +94,33 @@ TEST_F(BufferTest, SizeMatrixStd430) {
}
TEST_F(BufferTest, SizeMatrixStd140) {
- FormatParser fp;
- auto fmt = fp.Parse("R16G16_SINT");
- fmt->SetColumnCount(3);
- fmt->SetLayout(Format::Layout::kStd140);
+ TypeParser parser;
+ auto type = parser.Parse("R16G16_SINT");
+ type->SetColumnCount(3);
+ Format fmt(type.get());
+ fmt.SetLayout(Format::Layout::kStd140);
Buffer b(BufferType::kColor);
- b.SetFormat(fmt.get());
+ b.SetFormat(&fmt);
b.SetElementCount(10);
EXPECT_EQ(10, b.ElementCount());
- EXPECT_EQ(120, b.ValueCount());
+ EXPECT_EQ(10 * 2 * 3, 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);
+ TypeParser parser;
+ auto type = parser.Parse("R32G32B32_SINT");
+ type->SetColumnCount(3);
+ Format fmt(type.get());
Buffer b(BufferType::kColor);
- b.SetFormat(fmt.get());
+ b.SetFormat(&fmt);
b.SetValueCount(9);
EXPECT_EQ(1U, b.ElementCount());
- EXPECT_EQ(12U, b.ValueCount());
+ EXPECT_EQ(9U, b.ValueCount());
EXPECT_EQ(12U * sizeof(int32_t), b.GetSizeInBytes());
}
diff --git a/src/format.cc b/src/format.cc
index 66e5e76..221bcff 100644
--- a/src/format.cc
+++ b/src/format.cc
@@ -14,47 +14,75 @@
#include "src/format.h"
+#include <algorithm>
+#include <utility>
+
#include "src/make_unique.h"
+#include "src/type_parser.h"
namespace amber {
+namespace {
-Format::Format() = default;
+std::string FormatModeToName(FormatMode mode) {
+ switch (mode) {
+ case FormatMode::kUNorm:
+ return "UNORM";
+ case FormatMode::kUInt:
+ return "UINT";
+ case FormatMode::kUScaled:
+ return "USCALED";
+ case FormatMode::kSInt:
+ return "SINT";
+ case FormatMode::kSNorm:
+ return "SNORM";
+ case FormatMode::kSScaled:
+ return "SSCALED";
+ case FormatMode::kSRGB:
+ return "SRGB";
+ case FormatMode::kSFloat:
+ return "SFLOAT";
+ case FormatMode::kUFloat:
+ return "UFLOAT";
+ }
+
+ return "";
+}
+
+uint32_t CalculatePad(uint32_t val) {
+ if ((val % 16) == 0)
+ return 0;
+ return 16 - (val % 16);
+}
+
+} // namespace
+
+Format::Format(type::Type* type) : type_(type) {
+ auto name = GenerateName();
+ if (name == "")
+ format_type_ = FormatType::kUnknown;
+ else
+ format_type_ = TypeParser::NameToFormatType(name);
+ RebuildSegments();
+}
Format::~Format() = default;
uint32_t Format::SizeInBytes() const {
uint32_t size = 0;
- for (const auto& seg : segments_)
- size += static_cast<uint32_t>(seg.GetComponent()->SizeInBytes());
+ for (const auto& seg : segments_) {
+ if (seg.IsPadding()) {
+ size += seg.PaddingBytes();
+ continue;
+ }
+ size += static_cast<uint32_t>(seg.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)
- return false;
- }
- return true;
-}
-
bool Format::Equal(const Format* b) const {
- if (type_ != b->type_ || layout_ != b->layout_ ||
- pack_size_in_bytes_ != b->pack_size_in_bytes_ ||
- column_count_ != b->column_count_) {
- return false;
- }
- if (components_.size() != b->components_.size())
- 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) {
- return false;
- }
- }
- return true;
+ return format_type_ == b->format_type_ && layout_ == b->layout_ &&
+ type_->Equal(b->type_);
}
uint32_t Format::InputNeededPerElement() const {
@@ -68,18 +96,6 @@ uint32_t Format::InputNeededPerElement() const {
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::SetLayout(Layout layout) {
layout_ = layout;
RebuildSegments();
@@ -87,55 +103,308 @@ void Format::SetLayout(Layout layout) {
void Format::RebuildSegments() {
segments_.clear();
+ AddSegmentsForType(type_);
+}
+
+void Format::AddPaddedSegment(uint32_t size) {
+ // If the last item was already padding we just extend by the |size| bytes
+ if (!segments_.empty() && segments_.back().IsPadding()) {
+ segments_[segments_.size() - 1] =
+ Segment{size + segments_.back().SizeInBytes()};
+ } else {
+ segments_.push_back(Segment{size});
+ }
+}
+
+void Format::AddPaddedSegmentPackable(uint32_t size) {
+ AddPaddedSegment(size);
+ segments_.back().SetPackable(true);
+}
+
+bool Format::AddSegment(const Segment& seg) {
+ if (!segments_.empty()) {
+ auto last = segments_.back();
+
+ if (last.IsPackable() && last.IsPadding() &&
+ last.SizeInBytes() >= seg.SizeInBytes()) {
+ segments_.back() = seg;
+ auto pad = last.SizeInBytes() - seg.SizeInBytes();
+ if (pad > 0)
+ AddPaddedSegmentPackable(pad);
+
+ return false;
+ }
+ }
+ segments_.push_back(seg);
+ return true;
+}
+
+bool Format::NeedsPadding(type::Type* t) const {
+ if (layout_ == Layout::kStd140 && (t->IsMatrix() || t->IsArray()))
+ return true;
+ if (t->IsVec3() || (t->IsMatrix() && t->RowCount() == 3))
+ return true;
+ return false;
+}
+
+uint32_t Format::CalcVecBaseAlignmentInBytes(type::Number* n) const {
+ // vec3 rounds up to a Vec4, so 4 * N
+ if (n->IsVec3())
+ return 4 * n->SizeInBytes();
+
+ // vec2 and vec4 are 2 * N and 4 * N respectively
+ return n->RowCount() * n->SizeInBytes();
+}
+
+uint32_t Format::CalcArrayBaseAlignmentInBytes(type::Type* t) const {
+ uint32_t align = 0;
+ if (t->IsStruct()) {
+ align = CalcStructBaseAlignmentInBytes(t->AsStruct());
+ } else if (t->IsMatrix()) {
+ align = CalcMatrixBaseAlignmentInBytes(t->AsNumber());
+ } else if (t->IsVec()) {
+ align = CalcVecBaseAlignmentInBytes(t->AsNumber());
+ } else if (t->IsList()) {
+ align = CalcListBaseAlignmentInBytes(t->AsList());
+ } else if (t->IsNumber()) {
+ align = t->SizeInBytes();
+ }
+
+ // In std140 array elements round up to multiple of vec4.
+ if (layout_ == Layout::kStd140)
+ align += CalculatePad(align);
+
+ return align;
+}
+
+uint32_t Format::CalcStructBaseAlignmentInBytes(type::Struct* s) const {
+ uint32_t base_alignment = 0;
+ for (const auto& member : s->Members()) {
+ base_alignment =
+ std::max(base_alignment, CalcTypeBaseAlignmentInBytes(member.type));
+ }
+
+ return base_alignment;
+}
+
+uint32_t Format::CalcMatrixBaseAlignmentInBytes(type::Number* m) const {
+ // TODO(dsinclair): Deal with row major when needed. Currently this assumes
+ // the matrix is column major.
+
+ uint32_t align = 0;
+ if (m->RowCount() == 3)
+ align = 4 * m->SizeInBytes();
+ else
+ align = m->RowCount() * m->SizeInBytes();
- 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()});
+ // STD140 rounds up to 16 byte alignment
+ if (layout_ == Layout::kStd140)
+ align += CalculatePad(align);
+
+ return align;
+}
+
+uint32_t Format::CalcListBaseAlignmentInBytes(type::List* l) const {
+ return l->SizeInBytes();
+}
+
+uint32_t Format::CalcTypeBaseAlignmentInBytes(type::Type* t) const {
+ if (t->IsArray())
+ return CalcArrayBaseAlignmentInBytes(t);
+ if (t->IsVec())
+ return CalcVecBaseAlignmentInBytes(t->AsNumber());
+ if (t->IsMatrix())
+ return CalcMatrixBaseAlignmentInBytes(t->AsNumber());
+ if (t->IsNumber())
+ return t->SizeInBytes();
+ if (t->IsList())
+ return CalcListBaseAlignmentInBytes(t->AsList());
+ if (t->IsStruct()) {
+ // Pad struct to 16 bytes in STD140
+ uint32_t base = CalcStructBaseAlignmentInBytes(t->AsStruct());
+ if (layout_ == Layout::kStd140)
+ base += CalculatePad(base);
+ return base;
+ }
+
+ assert(false && "Not reached");
+ return 0;
+}
+
+uint32_t Format::AddSegmentsForType(type::Type* type) {
+ if (type->IsList() && type->AsList()->IsPacked()) {
+ auto l = type->AsList();
+ if (AddSegment(Segment(FormatComponentType::kR, FormatMode::kUInt,
+ l->PackSizeInBits()))) {
+ return l->SizeInBytes();
+ }
+ return 0;
+ }
+
+ // Remove packable from previous packing for types which can't pack back.
+ if (type->IsStruct() || type->IsVec() || type->IsMatrix() ||
+ type->IsArray()) {
+ if (!segments_.empty() && segments_.back().IsPadding())
+ segments_.back().SetPackable(false);
+ }
+
+ // TODO(dsinclair): How to handle matrix stride .... Stride comes from parent
+ // member ....
+
+ if (type->IsStruct()) {
+ auto s = type->AsStruct();
+ auto base_alignment_in_bytes = CalcStructBaseAlignmentInBytes(s);
+
+ uint32_t cur_offset = 0;
+ for (const auto& member : s->Members()) {
+ if (member.HasOffset()) {
+ assert(static_cast<uint32_t>(member.offset_in_bytes) >= cur_offset);
+
+ AddPaddedSegment(static_cast<uint32_t>(member.offset_in_bytes) -
+ cur_offset);
+ cur_offset = static_cast<uint32_t>(member.offset_in_bytes);
+ }
+
+ uint32_t seg_size = 0;
+ if (member.type->IsSizedArray()) {
+ for (size_t i = 0; i < member.type->ArraySize(); ++i) {
+ auto ary_seg_size = AddSegmentsForType(member.type);
+ // Don't allow array members to pack together
+ if (!segments_.empty() && segments_.back().IsPadding())
+ segments_.back().SetPackable(false);
+
+ if (member.HasArrayStride()) {
+ uint32_t array_stride =
+ static_cast<uint32_t>(member.array_stride_in_bytes);
+ assert(ary_seg_size <= array_stride &&
+ "Array element larger than stride");
+
+ seg_size += array_stride;
+ } else {
+ seg_size += ary_seg_size;
+ }
+ }
+ } else {
+ seg_size = AddSegmentsForType(member.type);
+ }
+
+ if (seg_size > 0 && seg_size < base_alignment_in_bytes) {
+ AddPaddedSegmentPackable(base_alignment_in_bytes - seg_size);
+ seg_size += base_alignment_in_bytes - seg_size;
+ }
+
+ cur_offset += seg_size;
+ }
+ if (s->HasStride()) {
+ assert(cur_offset <= s->StrideInBytes() &&
+ "Struct has more members then fit within stride");
+ AddPaddedSegment(s->StrideInBytes() - cur_offset);
+ cur_offset = s->StrideInBytes();
+ } else if (layout_ == Layout::kStd140) {
+ // Round struct up to 16 byte alignment in STD140.
+ auto pad = CalculatePad(cur_offset);
+ if (pad > 0) {
+ AddPaddedSegment(pad);
+ cur_offset += pad;
+ }
+ }
+ return cur_offset;
+ }
+
+ // List members are only numbers and must not be vecs or matrices.
+ if (type->IsList()) {
+ uint32_t size = 0;
+ auto l = type->AsList();
+ for (uint32_t i = 0; i < type->ColumnCount(); ++i) {
+ for (const auto& m : l->Members()) {
+ if (AddSegment(Segment{m.name, m.mode, m.num_bits}))
+ size += m.SizeInBytes();
+ }
+
+ if (NeedsPadding(type)) {
+ auto& seg = l->Members().back();
+ for (size_t k = 0; k < (4 - type->RowCount()); ++k) {
+ AddPaddedSegment(seg.SizeInBytes());
+ size += seg.SizeInBytes();
+ }
+ }
+ }
+ return size;
+ }
+
+ auto n = type->AsNumber();
+ uint32_t size = 0;
+ for (uint32_t i = 0; i < type->ColumnCount(); ++i) {
+ for (uint32_t k = 0; k < type->RowCount(); ++k) {
+ if (AddSegment(Segment{static_cast<FormatComponentType>(i),
+ n->GetFormatMode(), n->NumBits()})) {
+ size += type->SizeInBytes();
+ }
}
// 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 ((layout_ == Layout::kStd140 && 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();
+ if (NeedsPadding(type)) {
+ for (size_t k = 0; k < (4 - type->RowCount()); ++k) {
+ AddPaddedSegmentPackable(type->SizeInBytes());
+ size += type->SizeInBytes();
}
}
+
+ // Make sure matrix rows don't accidentally pack together.
+ if (type->IsMatrix() && segments_.back().IsPadding())
+ segments_.back().SetPackable(false);
}
+ return size;
}
std::string Format::GenerateName() const {
- std::string name = "";
- std::string parts = "ARGB";
- for (const auto& comp : components_) {
- name += parts[static_cast<uint8_t>(comp->type)] +
- std::to_string(comp->num_bits);
+ if (type_->IsMatrix())
+ return "";
+
+ static const char NAME_PARTS[] = "RGBAXDS";
+ if (type_->IsList()) {
+ std::vector<std::pair<std::string, std::string>> parts;
+ const auto& members = type_->AsList()->Members();
+ for (size_t i = 0; i < members.size(); ++i) {
+ const auto& member = members[i];
+ std::string name(1, NAME_PARTS[static_cast<uint8_t>(member.name)]);
+ name += std::to_string(member.num_bits);
+
+ std::string type = FormatModeToName(member.mode);
+ parts.push_back({name, type});
+ }
+
+ std::string name = "";
+ for (size_t i = 0; i < parts.size(); ++i) {
+ name += parts[i].first;
+
+ if (i + 1 < parts.size() && parts[i].second != parts[i + 1].second)
+ name += "_" + parts[i].second + "_";
+
+ // Handle the X8_D24 underscore.
+ if (parts[i].first[0] == 'X')
+ name += "_";
+ }
+ name += "_" + parts.back().second;
+ if (type_->AsList()->IsPacked())
+ name += "_PACK" + std::to_string(type_->AsList()->PackSizeInBits());
+
+ return name;
}
- name += "_";
- switch (components_[0]->mode) {
- case FormatMode::kUNorm:
- case FormatMode::kUFloat:
- case FormatMode::kUScaled:
- case FormatMode::kSNorm:
- case FormatMode::kSScaled:
- case FormatMode::kSRGB:
- return "";
- case FormatMode::kUInt:
- name += "UINT";
- break;
- case FormatMode::kSInt:
- name += "SINT";
- break;
- case FormatMode::kSFloat:
- name += "SFLOAT";
- break;
+
+ if (type_->IsNumber()) {
+ std::string name = "";
+ for (uint32_t i = 0; i < type_->RowCount(); ++i)
+ name += NAME_PARTS[i] + std::to_string(type_->SizeInBytes() * 8);
+
+ name += "_" + FormatModeToName(type_->AsNumber()->GetFormatMode());
+ return name;
}
- return name;
+
+ return "";
}
} // namespace amber
diff --git a/src/format.h b/src/format.h
index c101790..e6e68ba 100644
--- a/src/format.h
+++ b/src/format.h
@@ -17,12 +17,12 @@
#include <cassert>
#include <cstdint>
-#include <memory>
#include <string>
#include <vector>
#include "src/format_data.h"
#include "src/make_unique.h"
+#include "src/type.h"
namespace amber {
@@ -41,116 +41,70 @@ class Format {
public:
enum Layout { kStd140 = 0, kStd430 };
- /// Describes an individual component of a format.
- struct Component {
- Component(FormatComponentType t, FormatMode m, uint8_t bits)
- : type(t), mode(m), num_bits(bits) {}
-
- FormatComponentType type;
- FormatMode mode;
- uint8_t num_bits;
-
- /// Returns the number of bytes used to store this component.
- size_t SizeInBytes() const { return num_bits / 8; }
-
- /// Is this component represented by an 8 bit signed integer. (This includes
- /// int, scaled, rgb and norm values).
- bool IsInt8() const {
- return (mode == FormatMode::kSInt || mode == FormatMode::kSNorm ||
- mode == FormatMode::kSScaled || mode == FormatMode::kSRGB) &&
- num_bits == 8;
- }
- /// Is this component represented by a 16 bit signed integer. (This includes
- /// int and norm values)
- bool IsInt16() const {
- return (mode == FormatMode::kSInt || mode == FormatMode::kSNorm) &&
- num_bits == 16;
- }
- /// Is this component represented by a 32 bit signed integer.
- bool IsInt32() const { return mode == FormatMode::kSInt && num_bits == 32; }
- /// Is this component represented by a 64 bit signed integer.
- bool IsInt64() const { return mode == FormatMode::kSInt && num_bits == 64; }
- /// Is this component represented by an 8 bit unsigned integer. (This
- /// includes uint, unorm and uscaled values).
- bool IsUint8() const {
- return (mode == FormatMode::kUInt || mode == FormatMode::kUNorm ||
- mode == FormatMode::kUScaled) &&
- num_bits == 8;
- }
- /// Is this component represented by a 16 bit unsigned integer.
- bool IsUint16() const {
- return mode == FormatMode::kUInt && num_bits == 16;
- }
- /// Is this component represented by a 32 bit unsigned integer.
- bool IsUint32() const {
- return mode == FormatMode::kUInt && num_bits == 32;
- }
- /// Is this component represented by a 64 bit unsigned integer.
- bool IsUint64() const {
- return mode == FormatMode::kUInt && num_bits == 64;
- }
- /// Is this component represented by a 16 bit floating point value.
- bool IsFloat16() const {
- return mode == FormatMode::kSFloat && num_bits == 16;
- }
- /// Is this component represented by a 32 bit floating point value
- bool IsFloat() const {
- return mode == FormatMode::kSFloat && num_bits == 32;
- }
- /// Is this component represented by a 64 bit floating point value
- bool IsDouble() const {
- return mode == FormatMode::kSFloat && num_bits == 64;
- }
- };
-
class Segment {
public:
- explicit Segment(Component* component) : component_(component) {}
- Segment(const Segment&) = default;
- ~Segment() = default;
-
- Segment& operator=(const Segment&) = default;
+ explicit Segment(uint32_t num_bytes)
+ : is_padding_(true), num_bits_(num_bytes * 8) {}
+ Segment(FormatComponentType name, FormatMode mode, uint32_t num_bits)
+ : name_(name), mode_(mode), num_bits_(num_bits) {}
- void SetIsPadding() { is_padding_ = true; }
bool IsPadding() const { return is_padding_; }
+ uint32_t PaddingBytes() const { return num_bits_ / 8; }
- Component* GetComponent() const { return component_; }
+ FormatComponentType GetName() const { return name_; }
+ FormatMode GetFormatMode() const { return mode_; }
+ uint32_t GetNumBits() const { return num_bits_; }
+
+ uint32_t SizeInBytes() const { return num_bits_ / 8; }
+
+ // The packable flag can be set on padding segments. This means, the next
+ // byte, if it's the same type as this packing, can be inserted before
+ // this packing segment as long as it fits within the pack size, removing
+ // that much pack space.
+ bool IsPackable() const { return is_packable_; }
+ void SetPackable(bool packable) { is_packable_ = packable; }
private:
- Component* component_;
bool is_padding_ = false;
+ bool is_packable_ = false;
+ FormatComponentType name_ = FormatComponentType::kR;
+ FormatMode mode_ = FormatMode::kSInt;
+ uint32_t num_bits_ = 0;
};
/// Creates a format of unknown type.
- Format();
+ explicit Format(type::Type* type);
~Format();
+ static bool IsNormalized(FormatMode mode) {
+ return mode == FormatMode::kUNorm || mode == FormatMode::kSNorm ||
+ mode == FormatMode::kSRGB;
+ }
+
/// Returns true if |b| describes the same format as this object.
bool Equal(const Format* b) const;
/// Sets the type of the format. For image types this maps closely to the
/// list of Vulkan formats. For data types, this maybe Unknown if the data
/// type can not be represented by the image format (e.g. matrix types)
- void SetFormatType(FormatType type) { type_ = type; }
- FormatType GetFormatType() const { return type_; }
+ void SetFormatType(FormatType type) { format_type_ = type; }
+ FormatType GetFormatType() const { return format_type_; }
void SetLayout(Layout layout);
Layout GetLayout() const { return layout_; }
- /// Set the number of bytes this format is packed into, if provided.
- void SetPackSize(uint8_t size_in_bytes) {
- pack_size_in_bytes_ = size_in_bytes;
- }
- /// Retrieves the number of bytes this format is packed into.
- uint8_t GetPackSize() const { return pack_size_in_bytes_; }
+ type::Type* GetType() const { return type_; }
- void AddComponent(FormatComponentType type, FormatMode mode, uint8_t bits);
+ /// Returns a pointer to the only type in this format. Only valid if
+ /// there is only an int or float type, nullptr otherwise.
+ type::Type* GetOnlyType() const {
+ if (type_->IsNumber())
+ return type_;
+ return nullptr;
+ }
- /// Returns a pointer to the only component in this format. Only valid if
- /// there is only a single component, asserts otherwise.
- Component* GetOnlyComponent() const {
- assert(components_.size() == 1);
- return components_[0].get();
+ bool IsPacked() const {
+ return type_->IsList() && type_->AsList()->IsPacked();
}
/// The segment is the individual pieces of the components including padding.
@@ -159,19 +113,28 @@ class Format {
/// Returns the number of bytes this format requires.
uint32_t SizeInBytes() const;
- bool IsFormatKnown() const { return type_ != FormatType::kUnknown; }
+ bool IsFormatKnown() const { return format_type_ != FormatType::kUnknown; }
bool HasStencilComponent() const {
- return type_ == FormatType::kD24_UNORM_S8_UINT ||
- type_ == FormatType::kD16_UNORM_S8_UINT ||
- type_ == FormatType::kD32_SFLOAT_S8_UINT ||
- type_ == FormatType::kS8_UINT;
+ return format_type_ == FormatType::kD24_UNORM_S8_UINT ||
+ format_type_ == FormatType::kD16_UNORM_S8_UINT ||
+ format_type_ == FormatType::kD32_SFLOAT_S8_UINT ||
+ format_type_ == FormatType::kS8_UINT;
}
/// Returns true if the format components are normalized.
bool IsNormalized() const {
- FormatMode mode = components_.back()->mode;
- return mode == FormatMode::kUNorm || mode == FormatMode::kSNorm ||
- mode == FormatMode::kSRGB;
+ if (type_->IsNumber() && IsNormalized(type_->AsNumber()->GetFormatMode()))
+ return true;
+
+ if (type_->IsList()) {
+ for (auto& member : type_->AsList()->Members()) {
+ if (!IsNormalized(member.mode)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
}
/// Returns the number of input values required for an item of this format.
@@ -179,52 +142,93 @@ class Format {
/// account.
uint32_t InputNeededPerElement() const;
- /// 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 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);
-
/// Returns true if all components of this format are an 8 bit signed int.
- bool IsInt8() const { return AreAllComponents(FormatMode::kSInt, 8); }
+ bool IsInt8() const {
+ return type_->IsNumber() &&
+ type::Type::IsInt8(type_->AsNumber()->GetFormatMode(),
+ type_->AsNumber()->NumBits());
+ }
/// Returns true if all components of this format are a 16 bit signed int.
- bool IsInt16() const { return AreAllComponents(FormatMode::kSInt, 16); }
+ bool IsInt16() const {
+ return type_->IsNumber() &&
+ type::Type::IsInt16(type_->AsNumber()->GetFormatMode(),
+ type_->AsNumber()->NumBits());
+ }
/// Returns true if all components of this format are a 32 bit signed int.
- bool IsInt32() const { return AreAllComponents(FormatMode::kSInt, 32); }
+ bool IsInt32() const {
+ return type_->IsNumber() &&
+ type::Type::IsInt32(type_->AsNumber()->GetFormatMode(),
+ type_->AsNumber()->NumBits());
+ }
/// Returns true if all components of this format are a 64 bit signed int.
- bool IsInt64() const { return AreAllComponents(FormatMode::kSInt, 64); }
+ bool IsInt64() const {
+ return type_->IsNumber() &&
+ type::Type::IsInt64(type_->AsNumber()->GetFormatMode(),
+ type_->AsNumber()->NumBits());
+ }
/// Returns true if all components of this format are a 8 bit unsigned int.
- bool IsUint8() const { return AreAllComponents(FormatMode::kUInt, 8); }
+ bool IsUint8() const {
+ return type_->IsNumber() &&
+ type::Type::IsUint8(type_->AsNumber()->GetFormatMode(),
+ type_->AsNumber()->NumBits());
+ }
/// Returns true if all components of this format are a 16 bit unsigned int.
- bool IsUint16() const { return AreAllComponents(FormatMode::kUInt, 16); }
+ bool IsUint16() const {
+ return type_->IsNumber() &&
+ type::Type::IsUint16(type_->AsNumber()->GetFormatMode(),
+ type_->AsNumber()->NumBits());
+ }
/// Returns true if all components of this format are a 32 bit unsigned int.
- bool IsUint32() const { return AreAllComponents(FormatMode::kUInt, 32); }
+ bool IsUint32() const {
+ return type_->IsNumber() &&
+ type::Type::IsUint32(type_->AsNumber()->GetFormatMode(),
+ type_->AsNumber()->NumBits());
+ }
/// Returns true if all components of this format are a 64 bit unsigned int.
- bool IsUint64() const { return AreAllComponents(FormatMode::kUInt, 64); }
+ bool IsUint64() const {
+ return type_->IsNumber() &&
+ type::Type::IsUint64(type_->AsNumber()->GetFormatMode(),
+ type_->AsNumber()->NumBits());
+ }
/// Returns true if all components of this format are a 32 bit float.
- bool IsFloat() const { return AreAllComponents(FormatMode::kSFloat, 32); }
+ bool IsFloat32() const {
+ return type_->IsNumber() &&
+ type::Type::IsFloat32(type_->AsNumber()->GetFormatMode(),
+ type_->AsNumber()->NumBits());
+ }
/// Returns true if all components of this format are a 64 bit float.
- bool IsDouble() const { return AreAllComponents(FormatMode::kSFloat, 64); }
+ bool IsFloat64() const {
+ return type_->IsNumber() &&
+ type::Type::IsFloat64(type_->AsNumber()->GetFormatMode(),
+ type_->AsNumber()->NumBits());
+ }
- /// Generates the image format name for this format if possible. Returns
- /// the name if generated or "" otherwise.
- std::string GenerateName() const;
+ std::string GenerateNameForTesting() const { return GenerateName(); }
private:
- bool AreAllComponents(FormatMode mode, uint32_t bits) const;
void RebuildSegments();
+ uint32_t AddSegmentsForType(type::Type* type);
+ bool NeedsPadding(type::Type* t) const;
+ // Returns true if a segment was added, false if we packed the requested
+ // segment into previously allocated space.
+ bool AddSegment(const Segment& seg);
+ void AddPaddedSegment(uint32_t size);
+ void AddPaddedSegmentPackable(uint32_t size);
+ uint32_t CalcTypeBaseAlignmentInBytes(type::Type* s) const;
+ uint32_t CalcStructBaseAlignmentInBytes(type::Struct* s) const;
+ uint32_t CalcVecBaseAlignmentInBytes(type::Number* n) const;
+ uint32_t CalcArrayBaseAlignmentInBytes(type::Type* t) const;
+ uint32_t CalcMatrixBaseAlignmentInBytes(type::Number* m) const;
+ uint32_t CalcListBaseAlignmentInBytes(type::List* l) const;
+
+ /// Generates the image format name for this format if possible. Returns
+ /// the name if generated or "" otherwise.
+ std::string GenerateName() const;
- FormatType type_ = FormatType::kUnknown;
+ FormatType format_type_ = FormatType::kUnknown;
Layout layout_ = Layout::kStd430;
- uint8_t pack_size_in_bytes_ = 0;
- uint32_t column_count_ = 1;
- std::vector<std::unique_ptr<Component>> components_;
+ type::Type* type_;
+ std::vector<FormatComponentType> type_names_;
std::vector<Segment> segments_;
};
diff --git a/src/format_data.h b/src/format_data.h
index 98237bf..ff860c8 100644
--- a/src/format_data.h
+++ b/src/format_data.h
@@ -16,10 +16,10 @@
#define SRC_FORMAT_DATA_H_
enum class FormatComponentType {
- kA = 0,
- kR,
+ kR = 0,
kG,
kB,
+ kA,
kX,
kD,
kS,
diff --git a/src/format_parser.h b/src/format_parser.h
deleted file mode 100644
index 7257bf1..0000000
--- a/src/format_parser.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2019 The Amber Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef SRC_FORMAT_PARSER_H_
-#define SRC_FORMAT_PARSER_H_
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "src/format.h"
-
-namespace amber {
-
-/// Parses a Vulkan image string into a format object.
-class FormatParser {
- public:
- static FormatType NameToType(const std::string& data);
-
- FormatParser();
- ~FormatParser();
-
- std::unique_ptr<Format> Parse(const std::string& fmt);
-
- private:
- std::unique_ptr<Format> ParseGlslFormat(const std::string& fmt);
- void ProcessChunk(Format*, const std::string&);
- void AddPiece(FormatComponentType type, uint8_t bits);
- void FlushPieces(Format* fmt, FormatMode mode);
-
- struct Pieces {
- Pieces(FormatComponentType t, uint8_t bits) : type(t), num_bits(bits) {}
-
- FormatComponentType type;
- uint8_t num_bits;
- };
-
- std::vector<Pieces> pieces_;
-};
-
-} // namespace amber
-
-#endif // SRC_FORMAT_PARSER_H_
diff --git a/src/format_test.cc b/src/format_test.cc
index b148888..341faac 100644
--- a/src/format_test.cc
+++ b/src/format_test.cc
@@ -15,48 +15,49 @@
#include "src/format.h"
#include "gtest/gtest.h"
-#include "src/format_parser.h"
#include "src/make_unique.h"
+#include "src/type_parser.h"
namespace amber {
using FormatTest = testing::Test;
-TEST_F(FormatTest, SizeInBytesVector) {
- FormatParser fp;
- auto fmt = fp.Parse("R32G32B32_SFLOAT");
- ASSERT_TRUE(fmt != nullptr);
-
- EXPECT_EQ(3U, fmt->InputNeededPerElement());
- EXPECT_EQ(16U, fmt->SizeInBytes());
+TEST_F(FormatTest, DefaultToStd430) {
+ auto f32 = type::Number::Float(32);
+ Format fmt(f32.get());
+ EXPECT_EQ(Format::Layout::kStd430, fmt.GetLayout());
}
-TEST_F(FormatTest, SizeInBytesMatrix) {
- FormatParser fp;
- auto fmt = fp.Parse("R32G32B32_SFLOAT");
- ASSERT_TRUE(fmt != nullptr);
- fmt->SetColumnCount(3);
+TEST_F(FormatTest, SizeInBytesVector_Std430) {
+ TypeParser parser;
+ auto type = parser.Parse("R32G32B32_SFLOAT");
+ ASSERT_TRUE(type != nullptr);
- EXPECT_EQ(9U, fmt->InputNeededPerElement());
- EXPECT_EQ(48U, fmt->SizeInBytes());
+ Format fmt(type.get());
+ EXPECT_EQ(3U, fmt.InputNeededPerElement());
+ EXPECT_EQ(16U, fmt.SizeInBytes());
}
-TEST_F(FormatTest, SizeInBytesMatrixStd140) {
- FormatParser fp;
- auto fmt = fp.Parse("R32G32_SFLOAT");
- ASSERT_TRUE(fmt != nullptr);
- fmt->SetColumnCount(2);
- fmt->SetLayout(Format::Layout::kStd140);
+TEST_F(FormatTest, SizeInBytesMatrix_Std430) {
+ TypeParser parser;
+ auto type = parser.Parse("R32G32B32_SFLOAT");
+ ASSERT_TRUE(type != nullptr);
+ type->SetColumnCount(3);
- EXPECT_EQ(32U, fmt->SizeInBytes());
+ Format fmt(type.get());
+ EXPECT_EQ(9U, fmt.InputNeededPerElement());
+ EXPECT_EQ(48U, fmt.SizeInBytes());
}
-TEST_F(FormatTest, RowCount) {
- FormatParser fp;
- auto fmt = fp.Parse("R32G32B32_SFLOAT");
- ASSERT_TRUE(fmt != nullptr);
+TEST_F(FormatTest, SizeInBytesMatrix_Std140) {
+ TypeParser parser;
+ auto type = parser.Parse("R32G32_SFLOAT");
+ ASSERT_TRUE(type != nullptr);
+ type->SetColumnCount(2);
- EXPECT_EQ(3U, fmt->RowCount());
+ Format fmt(type.get());
+ fmt.SetLayout(Format::Format::Layout::kStd140);
+ EXPECT_EQ(32U, fmt.SizeInBytes());
}
struct StdData {
@@ -70,15 +71,17 @@ using FormatStdTest = testing::TestWithParam<StdData>;
TEST_P(FormatStdTest, Test) {
auto test_data = GetParam();
- FormatParser fp;
- auto fmt = fp.Parse(test_data.fmt);
- ASSERT_TRUE(fmt != nullptr) << test_data.name;
+ TypeParser parser;
+ auto type = parser.Parse(test_data.fmt);
+ ASSERT_TRUE(type != nullptr) << test_data.name;
+
+ type->SetColumnCount(test_data.column_count);
- fmt->SetColumnCount(test_data.column_count);
+ Format fmt(type.get());
if (test_data.is_std140)
- fmt->SetLayout(Format::Layout::kStd140);
+ fmt.SetLayout(Format::Format::Layout::kStd140);
- EXPECT_EQ(test_data.size_in_bytes, fmt->SizeInBytes()) << test_data.name;
+ EXPECT_EQ(test_data.size_in_bytes, fmt.SizeInBytes()) << test_data.name;
}
INSTANTIATE_TEST_SUITE_P(
@@ -107,4 +110,1074 @@ INSTANTIATE_TEST_SUITE_P(
StdData{"float-std430", "R32_SFLOAT", 1, false,
4U})); // NOLINT(whitespace/parens)
+struct Name {
+ const char* name;
+};
+using FormatNameTest = testing::TestWithParam<Name>;
+
+TEST_P(FormatNameTest, Test) {
+ auto test_data = GetParam();
+
+ TypeParser parser;
+ auto type = parser.Parse(test_data.name);
+ ASSERT_TRUE(type != nullptr) << test_data.name;
+
+ Format fmt(type.get());
+ EXPECT_EQ(test_data.name, fmt.GenerateNameForTesting());
+}
+INSTANTIATE_TEST_SUITE_P(
+ FormatNameGenerateTest,
+ FormatNameTest,
+ testing::Values(Name{"A1R5G5B5_UNORM_PACK16"},
+ Name{"A2B10G10R10_SINT_PACK32"},
+ Name{"A2B10G10R10_SNORM_PACK32"},
+ Name{"A2B10G10R10_SSCALED_PACK32"},
+ Name{"A2B10G10R10_UINT_PACK32"},
+ Name{"A2B10G10R10_UNORM_PACK32"},
+ Name{"A2B10G10R10_USCALED_PACK32"},
+ Name{"A2R10G10B10_SINT_PACK32"},
+ Name{"A2R10G10B10_SNORM_PACK32"},
+ Name{"A2R10G10B10_SSCALED_PACK32"},
+ Name{"A2R10G10B10_UINT_PACK32"},
+ Name{"A2R10G10B10_UNORM_PACK32"},
+ Name{"A2R10G10B10_USCALED_PACK32"},
+ Name{"A8B8G8R8_SINT_PACK32"},
+ Name{"A8B8G8R8_SNORM_PACK32"},
+ Name{"A8B8G8R8_SRGB_PACK32"},
+ Name{"A8B8G8R8_SSCALED_PACK32"},
+ Name{"A8B8G8R8_UINT_PACK32"},
+ Name{"A8B8G8R8_UNORM_PACK32"},
+ Name{"A8B8G8R8_USCALED_PACK32"},
+ Name{"B10G11R11_UFLOAT_PACK32"},
+ Name{"B4G4R4A4_UNORM_PACK16"},
+ Name{"B5G5R5A1_UNORM_PACK16"},
+ Name{"B5G6R5_UNORM_PACK16"},
+ Name{"B8G8R8A8_SINT"},
+ Name{"B8G8R8A8_SNORM"},
+ Name{"B8G8R8A8_SRGB"},
+ Name{"B8G8R8A8_SSCALED"},
+ Name{"B8G8R8A8_UINT"},
+ Name{"B8G8R8A8_UNORM"},
+ Name{"B8G8R8A8_USCALED"},
+ Name{"B8G8R8_SINT"},
+ Name{"B8G8R8_SNORM"},
+ Name{"B8G8R8_SRGB"},
+ Name{"B8G8R8_SSCALED"},
+ Name{"B8G8R8_UINT"},
+ Name{"B8G8R8_UNORM"},
+ Name{"B8G8R8_USCALED"},
+ Name{"D16_UNORM"},
+ Name{"D16_UNORM_S8_UINT"},
+ Name{"D24_UNORM_S8_UINT"},
+ Name{"D32_SFLOAT"},
+ Name{"D32_SFLOAT_S8_UINT"},
+ Name{"R16G16B16A16_SFLOAT"},
+ Name{"R16G16B16A16_SINT"},
+ Name{"R16G16B16A16_SNORM"},
+ Name{"R16G16B16A16_SSCALED"},
+ Name{"R16G16B16A16_UINT"},
+ Name{"R16G16B16A16_UNORM"},
+ Name{"R16G16B16A16_USCALED"},
+ Name{"R16G16B16_SFLOAT"},
+ Name{"R16G16B16_SINT"},
+ Name{"R16G16B16_SNORM"},
+ Name{"R16G16B16_SSCALED"},
+ Name{"R16G16B16_UINT"},
+ Name{"R16G16B16_UNORM"},
+ Name{"R16G16B16_USCALED"},
+ Name{"R16G16_SFLOAT"},
+ Name{"R16G16_SINT"},
+ Name{"R16G16_SNORM"},
+ Name{"R16G16_SSCALED"},
+ Name{"R16G16_UINT"},
+ Name{"R16G16_UNORM"},
+ Name{"R16G16_USCALED"},
+ Name{"R16_SFLOAT"},
+ Name{"R16_SINT"},
+ Name{"R16_SNORM"},
+ Name{"R16_SSCALED"},
+ Name{"R16_UINT"},
+ Name{"R16_UNORM"},
+ Name{"R16_USCALED"},
+ Name{"R32G32B32A32_SFLOAT"},
+ Name{"R32G32B32A32_SINT"},
+ Name{"R32G32B32A32_UINT"},
+ Name{"R32G32B32_SFLOAT"},
+ Name{"R32G32B32_SINT"},
+ Name{"R32G32B32_UINT"},
+ Name{"R32G32_SFLOAT"},
+ Name{"R32G32_SINT"},
+ Name{"R32G32_UINT"},
+ Name{"R32_SFLOAT"},
+ Name{"R32_SINT"},
+ Name{"R32_UINT"},
+ Name{"R4G4B4A4_UNORM_PACK16"},
+ Name{"R4G4_UNORM_PACK8"},
+ Name{"R5G5B5A1_UNORM_PACK16"},
+ Name{"R5G6B5_UNORM_PACK16"},
+ Name{"R64G64B64A64_SFLOAT"},
+ Name{"R64G64B64A64_SINT"},
+ Name{"R64G64B64A64_UINT"},
+ Name{"R64G64B64_SFLOAT"},
+ Name{"R64G64B64_SINT"},
+ Name{"R64G64B64_UINT"},
+ Name{"R64G64_SFLOAT"},
+ Name{"R64G64_SINT"},
+ Name{"R64G64_UINT"},
+ Name{"R64_SFLOAT"},
+ Name{"R64_SINT"},
+ Name{"R64_UINT"},
+ Name{"R8G8B8A8_SINT"},
+ Name{"R8G8B8A8_SNORM"},
+ Name{"R8G8B8A8_SRGB"},
+ Name{"R8G8B8A8_SSCALED"},
+ Name{"R8G8B8A8_UINT"},
+ Name{"R8G8B8A8_UNORM"},
+ Name{"R8G8B8A8_USCALED"},
+ Name{"R8G8B8_SINT"},
+ Name{"R8G8B8_SNORM"},
+ Name{"R8G8B8_SRGB"},
+ Name{"R8G8B8_SSCALED"},
+ Name{"R8G8B8_UINT"},
+ Name{"R8G8B8_UNORM"},
+ Name{"R8G8B8_USCALED"},
+ Name{"R8G8_SINT"},
+ Name{"R8G8_SNORM"},
+ Name{"R8G8_SRGB"},
+ Name{"R8G8_SSCALED"},
+ Name{"R8G8_UINT"},
+ Name{"R8G8_UNORM"},
+ Name{"R8G8_USCALED"},
+ Name{"R8_SINT"},
+ Name{"R8_SNORM"},
+ Name{"R8_SRGB"},
+ Name{"R8_SSCALED"},
+ Name{"R8_UINT"},
+ Name{"R8_UNORM"},
+ Name{"R8_USCALED"},
+ Name{"S8_UINT"},
+ Name{"X8_D24_UNORM_PACK32"})); // NOLINT(whitespace/parens)
+
+TEST_F(FormatTest, SegmentPackedList_Std430) {
+ TypeParser parser;
+ auto type = parser.Parse("A8B8G8R8_SINT_PACK32");
+
+ Format fmt(type.get());
+ EXPECT_EQ(4, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(1U, segs.size());
+ // Always packs into a unsigned ...
+ EXPECT_EQ(FormatMode::kUInt, segs[0].GetFormatMode());
+ EXPECT_EQ(4, segs[0].SizeInBytes());
+}
+
+TEST_F(FormatTest, SegmentListR32G32_Std140) {
+ TypeParser parser;
+ auto type = parser.Parse("R32G32_UINT");
+
+ Format fmt(type.get());
+ fmt.SetLayout(Format::Layout::kStd140);
+ EXPECT_EQ(8, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(2U, segs.size());
+ EXPECT_EQ(FormatMode::kUInt, segs[0].GetFormatMode());
+ EXPECT_EQ(4, segs[0].SizeInBytes());
+ EXPECT_EQ(FormatMode::kUInt, segs[1].GetFormatMode());
+ EXPECT_EQ(4, segs[1].SizeInBytes());
+}
+
+TEST_F(FormatTest, SegmentListR32G32B32_Std140) {
+ TypeParser parser;
+ auto type = parser.Parse("R32G32B32_UINT");
+
+ Format fmt(type.get());
+ fmt.SetLayout(Format::Layout::kStd140);
+ EXPECT_EQ(16, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(4U, segs.size());
+ EXPECT_EQ(FormatMode::kUInt, segs[0].GetFormatMode());
+ EXPECT_EQ(4, segs[0].SizeInBytes());
+ EXPECT_EQ(FormatMode::kUInt, segs[1].GetFormatMode());
+ EXPECT_EQ(4, segs[1].SizeInBytes());
+ EXPECT_EQ(FormatMode::kUInt, segs[2].GetFormatMode());
+ EXPECT_EQ(4, segs[2].SizeInBytes());
+ EXPECT_TRUE(segs[3].IsPadding());
+ EXPECT_EQ(4, segs[3].SizeInBytes());
+}
+
+TEST_F(FormatTest, SegmentListR32G32B32_Std430) {
+ TypeParser parser;
+ auto type = parser.Parse("R32G32B32_UINT");
+
+ Format fmt(type.get());
+ fmt.SetLayout(Format::Format::Layout::kStd430);
+ EXPECT_EQ(16, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(4U, segs.size());
+ EXPECT_EQ(FormatMode::kUInt, segs[0].GetFormatMode());
+ EXPECT_EQ(4, segs[0].SizeInBytes());
+ EXPECT_EQ(FormatMode::kUInt, segs[1].GetFormatMode());
+ EXPECT_EQ(4, segs[1].SizeInBytes());
+ EXPECT_EQ(FormatMode::kUInt, segs[2].GetFormatMode());
+ EXPECT_EQ(4, segs[2].SizeInBytes());
+ EXPECT_TRUE(segs[3].IsPadding());
+ EXPECT_EQ(4, segs[3].SizeInBytes());
+}
+
+TEST_F(FormatTest, SegmentMat2x2_Std140) {
+ TypeParser parser;
+ auto type = parser.Parse("R32G32_SFLOAT");
+ type->SetColumnCount(2);
+
+ Format fmt(type.get());
+ fmt.SetLayout(Format::Format::Layout::kStd140);
+ EXPECT_EQ(32, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(6U, segs.size());
+ EXPECT_EQ(FormatMode::kSFloat, segs[0].GetFormatMode());
+ EXPECT_EQ(4, segs[0].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[1].GetFormatMode());
+ EXPECT_EQ(4, segs[1].SizeInBytes());
+ EXPECT_TRUE(segs[2].IsPadding());
+ EXPECT_EQ(8, segs[2].SizeInBytes());
+
+ EXPECT_EQ(FormatMode::kSFloat, segs[3].GetFormatMode());
+ EXPECT_EQ(4, segs[3].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[4].GetFormatMode());
+ EXPECT_EQ(4, segs[4].SizeInBytes());
+ EXPECT_TRUE(segs[5].IsPadding());
+ EXPECT_EQ(8, segs[5].SizeInBytes());
+}
+
+TEST_F(FormatTest, SegmentMat2x2_Std430) {
+ TypeParser parser;
+ auto type = parser.Parse("R32G32_SFLOAT");
+ type->SetColumnCount(2);
+
+ Format fmt(type.get());
+ fmt.SetLayout(Format::Layout::kStd430);
+ EXPECT_EQ(16, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(4U, segs.size());
+ EXPECT_EQ(FormatMode::kSFloat, segs[0].GetFormatMode());
+ EXPECT_EQ(4, segs[0].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[1].GetFormatMode());
+ EXPECT_EQ(4, segs[1].SizeInBytes());
+
+ EXPECT_EQ(FormatMode::kSFloat, segs[2].GetFormatMode());
+ EXPECT_EQ(4, segs[2].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[3].GetFormatMode());
+ EXPECT_EQ(4, segs[3].SizeInBytes());
+}
+
+TEST_F(FormatTest, SegmentMat2x3_Std430) {
+ TypeParser parser;
+ auto type = parser.Parse("R32G32B32_SFLOAT");
+ type->SetColumnCount(2);
+
+ Format fmt(type.get());
+ fmt.SetLayout(Format::Layout::kStd430);
+ EXPECT_EQ(32, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(8U, segs.size());
+ EXPECT_EQ(FormatMode::kSFloat, segs[0].GetFormatMode());
+ EXPECT_EQ(4, segs[0].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[1].GetFormatMode());
+ EXPECT_EQ(4, segs[1].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[2].GetFormatMode());
+ EXPECT_EQ(4, segs[2].SizeInBytes());
+ EXPECT_TRUE(segs[3].IsPadding());
+ EXPECT_EQ(4, segs[3].SizeInBytes());
+
+ EXPECT_EQ(FormatMode::kSFloat, segs[4].GetFormatMode());
+ EXPECT_EQ(4, segs[4].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[5].GetFormatMode());
+ EXPECT_EQ(4, segs[5].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[6].GetFormatMode());
+ EXPECT_EQ(4, segs[6].SizeInBytes());
+ EXPECT_TRUE(segs[7].IsPadding());
+ EXPECT_EQ(4, segs[7].SizeInBytes());
+}
+
+TEST_F(FormatTest, SegmentRuntimeArray_Std140) {
+ TypeParser parser;
+ auto type = parser.Parse("R32_SFLOAT");
+ type->SetIsRuntimeArray();
+
+ Format fmt(type.get());
+ fmt.SetLayout(Format::Format::Layout::kStd140);
+ EXPECT_EQ(16, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(2U, segs.size());
+ EXPECT_EQ(FormatMode::kSFloat, segs[0].GetFormatMode());
+ EXPECT_EQ(4, segs[0].SizeInBytes());
+ EXPECT_TRUE(segs[1].IsPadding());
+ EXPECT_EQ(12, segs[1].SizeInBytes());
+}
+
+TEST_F(FormatTest, SegmentRuntimeArray_Std430) {
+ TypeParser parser;
+ auto type = parser.Parse("R32_SFLOAT");
+ type->SetIsRuntimeArray();
+
+ Format fmt(type.get());
+ fmt.SetLayout(Format::Layout::kStd430);
+ EXPECT_EQ(4, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(1U, segs.size());
+ EXPECT_EQ(FormatMode::kSFloat, segs[0].GetFormatMode());
+ EXPECT_EQ(4, segs[0].SizeInBytes());
+}
+
+// struct {
+// float x;
+// int32 y;
+// }
+TEST_F(FormatTest, SegmentStruct_Std140) {
+ auto s = MakeUnique<type::Struct>();
+ auto f32 = type::Number::Float(32);
+ auto u32 = type::Number::Uint(32);
+ s->AddMember(f32.get());
+ s->AddMember(u32.get());
+
+ Format fmt(s.get());
+ fmt.SetLayout(Format::Layout::kStd140);
+ EXPECT_EQ(16, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(3, segs.size());
+ EXPECT_EQ(FormatMode::kSFloat, segs[0].GetFormatMode());
+ EXPECT_EQ(4, segs[0].SizeInBytes());
+ EXPECT_EQ(FormatMode::kUInt, segs[1].GetFormatMode());
+ EXPECT_EQ(4, segs[1].SizeInBytes());
+ EXPECT_TRUE(segs[2].IsPadding());
+ EXPECT_EQ(8, segs[2].SizeInBytes());
+}
+TEST_F(FormatTest, SegmentStruct_Std430) {
+ auto s = MakeUnique<type::Struct>();
+ auto f32 = type::Number::Float(32);
+ auto u32 = type::Number::Uint(32);
+ s->AddMember(f32.get());
+ s->AddMember(u32.get());
+
+ Format fmt(s.get());
+ fmt.SetLayout(Format::Layout::kStd430);
+ EXPECT_EQ(8, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(2U, segs.size());
+ EXPECT_EQ(FormatMode::kSFloat, segs[0].GetFormatMode());
+ EXPECT_EQ(4, segs[0].SizeInBytes());
+ EXPECT_EQ(FormatMode::kUInt, segs[1].GetFormatMode());
+ EXPECT_EQ(4, segs[1].SizeInBytes());
+}
+
+// struct STRIDE 20 {
+// float x;
+// int32 y;
+// }
+// Note, the STRIDE is the stride over the entire structure.
+TEST_F(FormatTest, SegmentStructWithStride_Std140) {
+ auto s = MakeUnique<type::Struct>();
+ auto f32 = type::Number::Float(32);
+ auto u32 = type::Number::Uint(32);
+ s->AddMember(f32.get());
+ s->AddMember(u32.get());
+ s->SetStrideInBytes(20);
+
+ Format fmt(s.get());
+ fmt.SetLayout(Format::Layout::kStd140);
+ EXPECT_EQ(20, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(3U, segs.size());
+ EXPECT_EQ(FormatMode::kSFloat, segs[0].GetFormatMode());
+ EXPECT_EQ(4, segs[0].SizeInBytes());
+ EXPECT_EQ(FormatMode::kUInt, segs[1].GetFormatMode());
+ EXPECT_EQ(4, segs[1].SizeInBytes());
+ EXPECT_TRUE(segs[2].IsPadding());
+ EXPECT_EQ((20 - sizeof(float) - sizeof(uint32_t)), segs[2].SizeInBytes());
+}
+TEST_F(FormatTest, SegmentStructWithStride_Std430) {
+ auto s = MakeUnique<type::Struct>();
+ auto f32 = type::Number::Float(32);
+ auto u32 = type::Number::Uint(32);
+ s->AddMember(f32.get());
+ s->AddMember(u32.get());
+ s->SetStrideInBytes(20);
+
+ Format fmt(s.get());
+ fmt.SetLayout(Format::Layout::kStd430);
+ EXPECT_EQ(20, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(3U, segs.size());
+ EXPECT_EQ(FormatMode::kSFloat, segs[0].GetFormatMode());
+ EXPECT_EQ(32U, segs[0].GetNumBits());
+ EXPECT_EQ(FormatMode::kUInt, segs[1].GetFormatMode());
+ EXPECT_EQ(32U, segs[1].GetNumBits());
+ EXPECT_TRUE(segs[2].IsPadding());
+ EXPECT_EQ((20 - sizeof(float) - sizeof(uint32_t)) * 8, segs[2].GetNumBits());
+}
+
+// struct {
+// float x OFFSET 4;
+// int32 y;
+// }
+TEST_F(FormatTest, SegmentStructWithMemberOffset_Std140) {
+ auto s = MakeUnique<type::Struct>();
+ auto f32 = type::Number::Float(32);
+ auto u32 = type::Number::Uint(32);
+
+ auto m = s->AddMember(f32.get());
+ m->offset_in_bytes = 4;
+
+ s->AddMember(u32.get());
+
+ Format fmt(s.get());
+ fmt.SetLayout(Format::Layout::kStd140);
+ EXPECT_EQ(16, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(4U, segs.size());
+ EXPECT_TRUE(segs[0].IsPadding());
+ EXPECT_EQ(4, segs[0].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[1].GetFormatMode());
+ EXPECT_EQ(4, segs[1].SizeInBytes());
+ EXPECT_EQ(FormatMode::kUInt, segs[2].GetFormatMode());
+ EXPECT_EQ(4, segs[2].SizeInBytes());
+ EXPECT_TRUE(segs[3].IsPadding());
+ EXPECT_EQ(4, segs[3].SizeInBytes());
+}
+TEST_F(FormatTest, SegmentStructWithMemberOffset_Std430) {
+ auto s = MakeUnique<type::Struct>();
+ auto f32 = type::Number::Float(32);
+ auto u32 = type::Number::Uint(32);
+
+ auto m = s->AddMember(f32.get());
+ m->offset_in_bytes = 4;
+
+ s->AddMember(u32.get());
+
+ Format fmt(s.get());
+ fmt.SetLayout(Format::Layout::kStd430);
+ EXPECT_EQ(12, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(3U, segs.size());
+ EXPECT_TRUE(segs[0].IsPadding());
+ EXPECT_EQ(4, segs[0].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[1].GetFormatMode());
+ EXPECT_EQ(4, segs[1].SizeInBytes());
+ EXPECT_EQ(FormatMode::kUInt, segs[2].GetFormatMode());
+ EXPECT_EQ(4, segs[2].SizeInBytes());
+}
+
+// struct {
+// struct {
+// int32 a;
+// float b;
+// } x;
+// float y;
+// }
+TEST_F(FormatTest, SegmentStructWithStruct_Std140) {
+ auto x = MakeUnique<type::Struct>();
+ auto f32 = type::Number::Float(32);
+ auto i32 = type::Number::Int(32);
+ x->AddMember(i32.get());
+ x->AddMember(f32.get());
+
+ auto s = MakeUnique<type::Struct>();
+ s->AddMember(x.get());
+ s->AddMember(f32.get());
+
+ Format fmt(s.get());
+ fmt.SetLayout(Format::Layout::kStd140);
+ EXPECT_EQ(32, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(5U, segs.size());
+ EXPECT_EQ(FormatMode::kSInt, segs[0].GetFormatMode());
+ EXPECT_EQ(4, segs[0].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[1].GetFormatMode());
+ EXPECT_EQ(4, segs[1].SizeInBytes());
+ EXPECT_TRUE(segs[2].IsPadding());
+ EXPECT_EQ(8, segs[2].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[3].GetFormatMode());
+ EXPECT_EQ(4, segs[3].SizeInBytes());
+ EXPECT_TRUE(segs[4].IsPadding());
+ EXPECT_EQ(12, segs[4].SizeInBytes());
+}
+TEST_F(FormatTest, SegmentStructWithStruct_Std430) {
+ auto x = MakeUnique<type::Struct>();
+ auto f32 = type::Number::Float(32);
+ auto i32 = type::Number::Int(32);
+ x->AddMember(i32.get());
+ x->AddMember(f32.get());
+
+ auto s = MakeUnique<type::Struct>();
+ s->AddMember(x.get());
+ s->AddMember(f32.get());
+
+ Format fmt(s.get());
+ fmt.SetLayout(Format::Layout::kStd430);
+ EXPECT_EQ(12, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(3U, segs.size());
+ EXPECT_EQ(FormatMode::kSInt, segs[0].GetFormatMode());
+ EXPECT_EQ(4, segs[0].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[1].GetFormatMode());
+ EXPECT_EQ(4, segs[1].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[2].GetFormatMode());
+ EXPECT_EQ(4, segs[2].SizeInBytes());
+}
+
+// struct {
+// int32 w;
+// vec2<float> x;
+// float y;
+// }
+TEST_F(FormatTest, SegmentStructWithVec2_Std140) {
+ auto s = MakeUnique<type::Struct>();
+ auto f32 = type::Number::Float(32);
+ auto i32 = type::Number::Int(32);
+ auto vec2 = type::Number::Float(32);
+ vec2->SetRowCount(2);
+
+ s->AddMember(i32.get());
+ s->AddMember(vec2.get());
+ s->AddMember(f32.get());
+
+ Format fmt(s.get());
+ fmt.SetLayout(Format::Layout::kStd140);
+ EXPECT_EQ(32, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(6U, segs.size());
+ /* w */
+ EXPECT_EQ(FormatMode::kSInt, segs[0].GetFormatMode());
+ EXPECT_EQ(4, segs[0].SizeInBytes());
+ /* pad */
+ EXPECT_TRUE(segs[1].IsPadding());
+ EXPECT_EQ(4, segs[1].SizeInBytes());
+ /* vec2 */
+ EXPECT_EQ(FormatMode::kSFloat, segs[2].GetFormatMode());
+ EXPECT_EQ(4, segs[2].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[3].GetFormatMode());
+ EXPECT_EQ(4, segs[3].SizeInBytes());
+ /* y */
+ EXPECT_EQ(FormatMode::kSFloat, segs[4].GetFormatMode());
+ EXPECT_EQ(4, segs[4].SizeInBytes());
+ /* pad */
+ EXPECT_TRUE(segs[5].IsPadding());
+ EXPECT_EQ(12, segs[5].SizeInBytes());
+}
+TEST_F(FormatTest, SegmentStructWithVec2_Std430) {
+ auto s = MakeUnique<type::Struct>();
+ auto f32 = type::Number::Float(32);
+ auto i32 = type::Number::Int(32);
+ auto vec2 = type::Number::Float(32);
+ vec2->SetRowCount(2);
+
+ s->AddMember(i32.get());
+ s->AddMember(vec2.get());
+ s->AddMember(f32.get());
+
+ Format fmt(s.get());
+ fmt.SetLayout(Format::Layout::kStd430);
+ EXPECT_EQ(24, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(6U, segs.size());
+ /* w */
+ EXPECT_EQ(FormatMode::kSInt, segs[0].GetFormatMode());
+ EXPECT_EQ(4, segs[0].SizeInBytes());
+ /* pad */
+ EXPECT_TRUE(segs[1].IsPadding());
+ EXPECT_EQ(4, segs[1].SizeInBytes());
+ /* vec2 */
+ EXPECT_EQ(FormatMode::kSFloat, segs[2].GetFormatMode());
+ EXPECT_EQ(4, segs[2].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[3].GetFormatMode());
+ EXPECT_EQ(4, segs[3].SizeInBytes());
+ /* y */
+ EXPECT_EQ(FormatMode::kSFloat, segs[4].GetFormatMode());
+ EXPECT_EQ(4, segs[4].SizeInBytes());
+ /* pad */
+ EXPECT_TRUE(segs[5].IsPadding());
+ EXPECT_EQ(4, segs[5].SizeInBytes());
+}
+
+// struct {
+// int32 w;
+// vec3<float> x;
+// float y;
+// }
+TEST_F(FormatTest, SegmentStructWithFloatPackedToVec_Std140) {
+ auto s = MakeUnique<type::Struct>();
+ auto f32 = type::Number::Float(32);
+ auto i32 = type::Number::Int(32);
+ auto vec3 = type::Number::Float(32);
+ vec3->SetRowCount(3);
+
+ s->AddMember(i32.get());
+ s->AddMember(vec3.get());
+ s->AddMember(f32.get());
+
+ Format fmt(s.get());
+ fmt.SetLayout(Format::Layout::kStd140);
+ EXPECT_EQ(32, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(6U, segs.size());
+ /* w */
+ EXPECT_EQ(FormatMode::kSInt, segs[0].GetFormatMode());
+ EXPECT_EQ(4, segs[0].SizeInBytes());
+ /* pad */
+ EXPECT_TRUE(segs[1].IsPadding());
+ EXPECT_EQ(12, segs[1].SizeInBytes());
+ /* vec2 */
+ EXPECT_EQ(FormatMode::kSFloat, segs[2].GetFormatMode());
+ EXPECT_EQ(4, segs[2].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[3].GetFormatMode());
+ EXPECT_EQ(4, segs[3].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[4].GetFormatMode());
+ EXPECT_EQ(4, segs[4].SizeInBytes());
+ /* y */
+ EXPECT_EQ(FormatMode::kSFloat, segs[5].GetFormatMode());
+ EXPECT_EQ(4, segs[5].SizeInBytes());
+}
+TEST_F(FormatTest, SegmentStructWithFloatPackedToVec_Std430) {
+ auto s = MakeUnique<type::Struct>();
+ auto f32 = type::Number::Float(32);
+ auto i32 = type::Number::Int(32);
+ auto vec3 = type::Number::Float(32);
+ vec3->SetRowCount(3);
+
+ s->AddMember(i32.get());
+ s->AddMember(vec3.get());
+ s->AddMember(f32.get());
+
+ Format fmt(s.get());
+ fmt.SetLayout(Format::Layout::kStd430);
+ EXPECT_EQ(32, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(6U, segs.size());
+ /* w */
+ EXPECT_EQ(FormatMode::kSInt, segs[0].GetFormatMode());
+ EXPECT_EQ(4, segs[0].SizeInBytes());
+ /* pad */
+ EXPECT_TRUE(segs[1].IsPadding());
+ EXPECT_EQ(12, segs[1].SizeInBytes());
+ /* vec2 */
+ EXPECT_EQ(FormatMode::kSFloat, segs[2].GetFormatMode());
+ EXPECT_EQ(4, segs[2].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[3].GetFormatMode());
+ EXPECT_EQ(4, segs[3].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[4].GetFormatMode());
+ EXPECT_EQ(4, segs[4].SizeInBytes());
+ /* y */
+ EXPECT_EQ(FormatMode::kSFloat, segs[5].GetFormatMode());
+ EXPECT_EQ(4, segs[5].SizeInBytes());
+}
+
+// struct {
+// int32 w;
+// vec3<float> x;
+// vec2<float> y;
+// }
+TEST_F(FormatTest, SegmentStructVec3Vec2_Std140) {
+ auto s = MakeUnique<type::Struct>();
+ auto i32 = type::Number::Int(32);
+ auto vec3 = type::Number::Float(32);
+ vec3->SetRowCount(3);
+ auto vec2 = type::Number::Float(32);
+ vec2->SetRowCount(2);
+
+ s->AddMember(i32.get());
+ s->AddMember(vec3.get());
+ s->AddMember(vec2.get());
+
+ Format fmt(s.get());
+ fmt.SetLayout(Format::Layout::kStd140);
+ EXPECT_EQ(48, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(9U, segs.size());
+ /* w */
+ EXPECT_EQ(FormatMode::kSInt, segs[0].GetFormatMode());
+ EXPECT_EQ(4, segs[0].SizeInBytes());
+ /* pad */
+ EXPECT_TRUE(segs[1].IsPadding());
+ EXPECT_EQ(12, segs[1].SizeInBytes());
+ /* vec3 */
+ EXPECT_EQ(FormatMode::kSFloat, segs[2].GetFormatMode());
+ EXPECT_EQ(4, segs[2].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[3].GetFormatMode());
+ EXPECT_EQ(4, segs[3].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[4].GetFormatMode());
+ EXPECT_EQ(4, segs[4].SizeInBytes());
+ /* pad */
+ EXPECT_TRUE(segs[5].IsPadding());
+ EXPECT_EQ(4, segs[5].SizeInBytes());
+ /* vec2 */
+ EXPECT_EQ(FormatMode::kSFloat, segs[6].GetFormatMode());
+ EXPECT_EQ(4, segs[6].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[7].GetFormatMode());
+ EXPECT_EQ(4, segs[7].SizeInBytes());
+ /* pad */
+ EXPECT_TRUE(segs[8].IsPadding());
+ EXPECT_EQ(8, segs[8].SizeInBytes());
+}
+TEST_F(FormatTest, SegmentStructVec3Vec2_Std430) {
+ auto s = MakeUnique<type::Struct>();
+ auto i32 = type::Number::Int(32);
+ auto vec3 = type::Number::Float(32);
+ vec3->SetRowCount(3);
+ auto vec2 = type::Number::Float(32);
+ vec2->SetRowCount(2);
+
+ s->AddMember(i32.get());
+ s->AddMember(vec3.get());
+ s->AddMember(vec2.get());
+
+ Format fmt(s.get());
+ fmt.SetLayout(Format::Layout::kStd430);
+ EXPECT_EQ(48, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(9U, segs.size());
+ /* w */
+ EXPECT_EQ(FormatMode::kSInt, segs[0].GetFormatMode());
+ EXPECT_EQ(4, segs[0].SizeInBytes());
+ /* pad */
+ EXPECT_TRUE(segs[1].IsPadding());
+ EXPECT_EQ(12, segs[1].SizeInBytes());
+ /* vec3 */
+ EXPECT_EQ(FormatMode::kSFloat, segs[2].GetFormatMode());
+ EXPECT_EQ(4, segs[2].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[3].GetFormatMode());
+ EXPECT_EQ(4, segs[3].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[4].GetFormatMode());
+ EXPECT_EQ(4, segs[4].SizeInBytes());
+ /* pad */
+ EXPECT_TRUE(segs[5].IsPadding());
+ EXPECT_EQ(4, segs[5].SizeInBytes());
+ /* vec2 */
+ EXPECT_EQ(FormatMode::kSFloat, segs[6].GetFormatMode());
+ EXPECT_EQ(4, segs[6].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[7].GetFormatMode());
+ EXPECT_EQ(4, segs[7].SizeInBytes());
+ /* pad */
+ EXPECT_TRUE(segs[8].IsPadding());
+ EXPECT_EQ(8, segs[8].SizeInBytes());
+}
+
+// struct {
+// int32 w;
+// mat2x2<float> x;
+// float y;
+// }
+TEST_F(FormatTest, SegmentStructMat2x2_Std140) {
+ auto s = MakeUnique<type::Struct>();
+ auto f32 = type::Number::Float(32);
+ auto i32 = type::Number::Int(32);
+ auto mat2x2 = type::Number::Float(32);
+ mat2x2->SetRowCount(2);
+ mat2x2->SetColumnCount(2);
+
+ s->AddMember(i32.get());
+ s->AddMember(mat2x2.get());
+ s->AddMember(f32.get());
+
+ Format fmt(s.get());
+ fmt.SetLayout(Format::Layout::kStd140);
+ EXPECT_EQ(64, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(10U, segs.size());
+ /* w */
+ EXPECT_EQ(FormatMode::kSInt, segs[0].GetFormatMode());
+ EXPECT_EQ(4, segs[0].SizeInBytes());
+ /* pad */
+ EXPECT_TRUE(segs[1].IsPadding());
+ EXPECT_EQ(12, segs[1].SizeInBytes());
+ /* column 1 */
+ EXPECT_EQ(FormatMode::kSFloat, segs[2].GetFormatMode());
+ EXPECT_EQ(4, segs[2].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[3].GetFormatMode());
+ EXPECT_EQ(4, segs[3].SizeInBytes());
+ EXPECT_TRUE(segs[4].IsPadding());
+ EXPECT_EQ(8, segs[4].SizeInBytes());
+ /* column 2 */
+ EXPECT_EQ(FormatMode::kSFloat, segs[5].GetFormatMode());
+ EXPECT_EQ(4, segs[5].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[6].GetFormatMode());
+ EXPECT_EQ(4, segs[6].SizeInBytes());
+ EXPECT_TRUE(segs[7].IsPadding());
+ EXPECT_EQ(8, segs[7].SizeInBytes());
+ /* y */
+ EXPECT_EQ(FormatMode::kSFloat, segs[8].GetFormatMode());
+ EXPECT_EQ(4, segs[8].SizeInBytes());
+ /* pad */
+ EXPECT_TRUE(segs[9].IsPadding());
+ EXPECT_EQ(12, segs[9].SizeInBytes());
+}
+TEST_F(FormatTest, SegmentStructMat2x2_Std430) {
+ auto s = MakeUnique<type::Struct>();
+ auto f32 = type::Number::Float(32);
+ auto i32 = type::Number::Int(32);
+ auto mat2x2 = type::Number::Float(32);
+ mat2x2->SetRowCount(2);
+ mat2x2->SetColumnCount(2);
+
+ s->AddMember(i32.get());
+ s->AddMember(mat2x2.get());
+ s->AddMember(f32.get());
+
+ Format fmt(s.get());
+ fmt.SetLayout(Format::Layout::kStd430);
+ EXPECT_EQ(32, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(8U, segs.size());
+ /* w */
+ EXPECT_EQ(FormatMode::kSInt, segs[0].GetFormatMode());
+ EXPECT_EQ(4, segs[0].SizeInBytes());
+ /* pad */
+ EXPECT_TRUE(segs[1].IsPadding());
+ EXPECT_EQ(4, segs[1].SizeInBytes());
+ /* column 1 */
+ EXPECT_EQ(FormatMode::kSFloat, segs[2].GetFormatMode());
+ EXPECT_EQ(4, segs[2].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[3].GetFormatMode());
+ EXPECT_EQ(4, segs[3].SizeInBytes());
+ /* column 2 */
+ EXPECT_EQ(FormatMode::kSFloat, segs[4].GetFormatMode());
+ EXPECT_EQ(4, segs[4].SizeInBytes());
+ EXPECT_EQ(FormatMode::kSFloat, segs[5].GetFormatMode());
+ EXPECT_EQ(4, segs[5].SizeInBytes());
+ /* y */
+ EXPECT_EQ(FormatMode::kSFloat, segs[6].GetFormatMode());
+ EXPECT_EQ(4, segs[6].SizeInBytes());
+ /* pad */
+ EXPECT_TRUE(segs[7].IsPadding());
+ EXPECT_EQ(4, segs[7].SizeInBytes());
+}
+
+// struct {
+// int32 w;
+// struct {
+// int32 a;
+// int32 b;
+// float c;
+// } x;
+// float y;
+// }
+TEST_F(FormatTest, SegmentStructWithStructNoPack_Std140) {
+ auto s = MakeUnique<type::Struct>();
+ auto f32 = type::Number::Float(32);
+ auto i32 = type::Number::Int(32);
+ auto x = MakeUnique<type::Struct>();
+ x->AddMember(i32.get());
+ x->AddMember(i32.get());
+ x->AddMember(f32.get());
+
+ s->AddMember(i32.get());
+ s->AddMember(x.get());
+ s->AddMember(f32.get());
+
+ Format fmt(s.get());
+ fmt.SetLayout(Format::Layout::kStd140);
+ EXPECT_EQ(48, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(8U, segs.size());
+ /* w */
+ EXPECT_EQ(FormatMode::kSInt, segs[0].GetFormatMode());
+ EXPECT_EQ(4, segs[0].SizeInBytes());
+ /* pad */
+ EXPECT_TRUE(segs[1].IsPadding());
+ EXPECT_EQ(12, segs[1].SizeInBytes());
+ /* a */
+ EXPECT_EQ(FormatMode::kSInt, segs[2].GetFormatMode());
+ EXPECT_EQ(4, segs[2].SizeInBytes());
+ /* b */
+ EXPECT_EQ(FormatMode::kSInt, segs[3].GetFormatMode());
+ EXPECT_EQ(4, segs[3].SizeInBytes());
+ /* c */
+ EXPECT_EQ(FormatMode::kSFloat, segs[4].GetFormatMode());
+ EXPECT_EQ(4, segs[4].SizeInBytes());
+ /* pad */
+ EXPECT_TRUE(segs[5].IsPadding());
+ EXPECT_EQ(4, segs[5].SizeInBytes());
+ /* y */
+ EXPECT_EQ(FormatMode::kSFloat, segs[6].GetFormatMode());
+ EXPECT_EQ(4, segs[6].SizeInBytes());
+ /* pad */
+ EXPECT_TRUE(segs[7].IsPadding());
+ EXPECT_EQ(12, segs[7].SizeInBytes());
+}
+TEST_F(FormatTest, SegmentStructWithStructNoPack_Std430) {
+ auto s = MakeUnique<type::Struct>();
+ auto f32 = type::Number::Float(32);
+ auto i32 = type::Number::Int(32);
+ auto x = MakeUnique<type::Struct>();
+ x->AddMember(i32.get());
+ x->AddMember(i32.get());
+ x->AddMember(f32.get());
+
+ s->AddMember(i32.get());
+ s->AddMember(x.get());
+ s->AddMember(f32.get());
+
+ Format fmt(s.get());
+ fmt.SetLayout(Format::Layout::kStd430);
+ EXPECT_EQ(20, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(5U, segs.size());
+ /* w */
+ EXPECT_EQ(FormatMode::kSInt, segs[0].GetFormatMode());
+ EXPECT_EQ(4, segs[0].SizeInBytes());
+ /* a */
+ EXPECT_EQ(FormatMode::kSInt, segs[1].GetFormatMode());
+ EXPECT_EQ(4, segs[1].SizeInBytes());
+ /* b */
+ EXPECT_EQ(FormatMode::kSInt, segs[2].GetFormatMode());
+ EXPECT_EQ(4, segs[2].SizeInBytes());
+ /* c */
+ EXPECT_EQ(FormatMode::kSFloat, segs[3].GetFormatMode());
+ EXPECT_EQ(4, segs[3].SizeInBytes());
+ /* y */
+ EXPECT_EQ(FormatMode::kSFloat, segs[4].GetFormatMode());
+ EXPECT_EQ(4, segs[4].SizeInBytes());
+}
+
+// struct {
+// int32 w;
+// struct {
+// int32 a;
+// int32 b;
+// float c[3];
+// } x;
+// float y;
+// }
+TEST_F(FormatTest, SegmentStructWithStructArray_Std140) {
+ auto s = MakeUnique<type::Struct>();
+ auto f32 = type::Number::Float(32);
+ auto i32 = type::Number::Int(32);
+ auto f32_ary = type::Number::Float(32);
+ f32_ary->SetIsSizedArray(3);
+
+ auto x = MakeUnique<type::Struct>();
+ x->AddMember(i32.get());
+ x->AddMember(i32.get());
+ x->AddMember(f32_ary.get());
+
+ s->AddMember(i32.get());
+ s->AddMember(x.get());
+ s->AddMember(f32.get());
+
+ Format fmt(s.get());
+ fmt.SetLayout(Format::Layout::kStd140);
+ EXPECT_EQ(96, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(13U, segs.size());
+ /* w */
+ EXPECT_EQ(FormatMode::kSInt, segs[0].GetFormatMode());
+ EXPECT_EQ(4, segs[0].SizeInBytes());
+ /* pad */
+ EXPECT_TRUE(segs[1].IsPadding());
+ EXPECT_EQ(12, segs[1].SizeInBytes());
+ /* a */
+ EXPECT_EQ(FormatMode::kSInt, segs[2].GetFormatMode());
+ EXPECT_EQ(4, segs[2].SizeInBytes());
+ /* b */
+ EXPECT_EQ(FormatMode::kSInt, segs[3].GetFormatMode());
+ EXPECT_EQ(4, segs[3].SizeInBytes());
+ /* pad */
+ EXPECT_TRUE(segs[4].IsPadding());
+ EXPECT_EQ(8, segs[4].SizeInBytes());
+ /* c[0] */
+ EXPECT_EQ(FormatMode::kSFloat, segs[5].GetFormatMode());
+ EXPECT_EQ(4, segs[5].SizeInBytes());
+ /* pad */
+ EXPECT_TRUE(segs[6].IsPadding());
+ EXPECT_EQ(12, segs[6].SizeInBytes());
+ /* c[1] */
+ EXPECT_EQ(FormatMode::kSFloat, segs[7].GetFormatMode());
+ EXPECT_EQ(4, segs[7].SizeInBytes());
+ /* pad */
+ EXPECT_TRUE(segs[8].IsPadding());
+ EXPECT_EQ(12, segs[8].SizeInBytes());
+ /* c[2] */
+ EXPECT_EQ(FormatMode::kSFloat, segs[9].GetFormatMode());
+ EXPECT_EQ(4, segs[9].SizeInBytes());
+ /* pad */
+ EXPECT_TRUE(segs[10].IsPadding());
+ EXPECT_EQ(12, segs[10].SizeInBytes());
+ /* y */
+ EXPECT_EQ(FormatMode::kSFloat, segs[11].GetFormatMode());
+ EXPECT_EQ(4, segs[11].SizeInBytes());
+ /* pad */
+ EXPECT_TRUE(segs[12].IsPadding());
+ EXPECT_EQ(12, segs[12].SizeInBytes());
+}
+TEST_F(FormatTest, SegmentStructWithStructArray_Std430) {
+ auto s = MakeUnique<type::Struct>();
+ auto f32 = type::Number::Float(32);
+ auto i32 = type::Number::Int(32);
+ auto f32_ary = type::Number::Float(32);
+ f32_ary->SetIsSizedArray(3);
+ auto x = MakeUnique<type::Struct>();
+ x->AddMember(i32.get());
+ x->AddMember(i32.get());
+ x->AddMember(f32_ary.get());
+
+ s->AddMember(i32.get());
+ s->AddMember(x.get());
+ s->AddMember(f32.get());
+
+ Format fmt(s.get());
+ fmt.SetLayout(Format::Layout::kStd430);
+ EXPECT_EQ(28, fmt.SizeInBytes());
+
+ const auto& segs = fmt.GetSegments();
+ ASSERT_EQ(7U, segs.size());
+ /* w */
+ EXPECT_EQ(FormatMode::kSInt, segs[0].GetFormatMode());
+ EXPECT_EQ(4, segs[0].SizeInBytes());
+ /* a */
+ EXPECT_EQ(FormatMode::kSInt, segs[1].GetFormatMode());
+ EXPECT_EQ(4, segs[1].SizeInBytes());
+ /* b */
+ EXPECT_EQ(FormatMode::kSInt, segs[2].GetFormatMode());
+ EXPECT_EQ(4, segs[2].SizeInBytes());
+ /* c[0] */
+ EXPECT_EQ(FormatMode::kSFloat, segs[3].GetFormatMode());
+ EXPECT_EQ(4, segs[3].SizeInBytes());
+ /* c[1] */
+ EXPECT_EQ(FormatMode::kSFloat, segs[4].GetFormatMode());
+ EXPECT_EQ(4, segs[4].SizeInBytes());
+ /* c[2] */
+ EXPECT_EQ(FormatMode::kSFloat, segs[5].GetFormatMode());
+ EXPECT_EQ(4, segs[5].SizeInBytes());
+ /* y */
+ EXPECT_EQ(FormatMode::kSFloat, segs[6].GetFormatMode());
+ EXPECT_EQ(4, segs[6].SizeInBytes());
+}
+
} // namespace amber
diff --git a/src/pipeline.cc b/src/pipeline.cc
index 5d0d030..8f23ca0 100644
--- a/src/pipeline.cc
+++ b/src/pipeline.cc
@@ -18,8 +18,8 @@
#include <limits>
#include <set>
-#include "src/format_parser.h"
#include "src/make_unique.h"
+#include "src/type_parser.h"
namespace amber {
namespace {
@@ -311,26 +311,30 @@ Result Pipeline::SetPushConstantBuffer(Buffer* buf) {
}
std::unique_ptr<Buffer> Pipeline::GenerateDefaultColorAttachmentBuffer() {
- FormatParser fp;
- auto fmt = fp.Parse(kDefaultColorBufferFormat);
+ TypeParser parser;
+ auto type = parser.Parse(kDefaultColorBufferFormat);
+ auto fmt = MakeUnique<Format>(type.get());
std::unique_ptr<Buffer> buf = MakeUnique<Buffer>(BufferType::kColor);
buf->SetName(kGeneratedColorBuffer);
buf->SetFormat(fmt.get());
formats_.push_back(std::move(fmt));
+ types_.push_back(std::move(type));
return buf;
}
std::unique_ptr<Buffer> Pipeline::GenerateDefaultDepthAttachmentBuffer() {
- FormatParser fp;
- auto fmt = fp.Parse(kDefaultDepthBufferFormat);
+ TypeParser parser;
+ auto type = parser.Parse(kDefaultDepthBufferFormat);
+ auto fmt = MakeUnique<Format>(type.get());
std::unique_ptr<Buffer> buf = MakeUnique<Buffer>(BufferType::kDepth);
buf->SetName(kGeneratedDepthBuffer);
buf->SetFormat(fmt.get());
formats_.push_back(std::move(fmt));
+ types_.push_back(std::move(type));
return buf;
}
@@ -548,10 +552,12 @@ Result Pipeline::GenerateOpenCLPodBuffers() {
// Use an 8-bit type because all the data in the descriptor map is
// byte-based and it simplifies the logic for sizing below.
- FormatParser fp;
- auto fmt = fp.Parse("R8_UINT");
+ TypeParser parser;
+ auto type = parser.Parse("R8_UINT");
+ auto fmt = MakeUnique<Format>(type.get());
buffer->SetFormat(fmt.get());
formats_.push_back(std::move(fmt));
+ types_.push_back(std::move(type));
buffer->SetName(GetName() + "_pod_buffer_" +
std::to_string(descriptor_set) + "_" +
diff --git a/src/pipeline.h b/src/pipeline.h
index a13347c..e874613 100644
--- a/src/pipeline.h
+++ b/src/pipeline.h
@@ -271,6 +271,7 @@ class Pipeline {
std::vector<BufferInfo> color_attachments_;
std::vector<BufferInfo> vertex_buffers_;
std::vector<BufferInfo> buffers_;
+ std::vector<std::unique_ptr<type::Type>> types_;
std::vector<std::unique_ptr<Format>> formats_;
BufferInfo depth_buffer_;
BufferInfo push_constant_buffer_;
diff --git a/src/pipeline_test.cc b/src/pipeline_test.cc
index 55d86e5..dd5064b 100644
--- a/src/pipeline_test.cc
+++ b/src/pipeline_test.cc
@@ -15,8 +15,8 @@
#include "src/pipeline.h"
#include "gtest/gtest.h"
-#include "src/format_parser.h"
#include "src/make_unique.h"
+#include "src/type_parser.h"
namespace amber {
namespace {
@@ -525,9 +525,11 @@ TEST_F(PipelineTest, OpenCLGeneratePodBuffers) {
Value int_value;
int_value.SetIntValue(1);
- FormatParser fp;
- auto int_fmt = fp.Parse("R32_SINT");
- auto char_fmt = fp.Parse("R8_SINT");
+ TypeParser parser;
+ auto int_type = parser.Parse("R32_SINT");
+ auto int_fmt = MakeUnique<Format>(int_type.get());
+ auto char_type = parser.Parse("R8_SINT");
+ auto char_fmt = MakeUnique<Format>(char_type.get());
Pipeline::ArgSetInfo arg_info1;
arg_info1.name = "arg_a";
@@ -589,8 +591,9 @@ TEST_F(PipelineTest, OpenCLGeneratePodBuffersBadName) {
Value int_value;
int_value.SetIntValue(1);
- FormatParser fp;
- auto int_fmt = fp.Parse("R32_SINT");
+ TypeParser parser;
+ auto int_type = parser.Parse("R32_SINT");
+ auto int_fmt = MakeUnique<Format>(int_type.get());
Pipeline::ArgSetInfo arg_info1;
arg_info1.name = "arg_z";
@@ -631,8 +634,9 @@ TEST_F(PipelineTest, OpenCLGeneratePodBuffersBadSize) {
Value int_value;
int_value.SetIntValue(1);
- FormatParser fp;
- auto short_fmt = fp.Parse("R16_SINT");
+ TypeParser parser;
+ auto short_type = parser.Parse("R16_SINT");
+ auto short_fmt = MakeUnique<Format>(short_type.get());
Pipeline::ArgSetInfo arg_info1;
arg_info1.name = "";
@@ -691,9 +695,11 @@ TEST_F(PipelineTest, OpenCLClone) {
Value int_value;
int_value.SetIntValue(1);
- FormatParser fp;
- auto int_fmt = fp.Parse("R32_SINT");
- auto char_fmt = fp.Parse("R8_SINT");
+ TypeParser parser;
+ auto int_type = parser.Parse("R32_SINT");
+ auto int_fmt = MakeUnique<Format>(int_type.get());
+ auto char_type = parser.Parse("R8_SINT");
+ auto char_fmt = MakeUnique<Format>(char_type.get());
Pipeline::ArgSetInfo arg_info1;
arg_info1.name = "arg_a";
diff --git a/src/script.h b/src/script.h
index 62b4433..51cf70e 100644
--- a/src/script.h
+++ b/src/script.h
@@ -171,11 +171,18 @@ class Script : public RecipeImpl {
/// Retrieves the SPIR-V target environment.
const std::string& GetSpvTargetEnv() const { return spv_env_; }
+ /// Assign ownership of the format to the script.
Format* RegisterFormat(std::unique_ptr<Format> fmt) {
formats_.push_back(std::move(fmt));
return formats_.back().get();
}
+ /// Assigns ownership of the type to the script.
+ type::Type* RegisterType(std::unique_ptr<type::Type> type) {
+ types_.push_back(std::move(type));
+ return types_.back().get();
+ }
+
private:
struct {
std::vector<std::string> required_features;
@@ -192,6 +199,7 @@ class Script : public RecipeImpl {
std::vector<std::unique_ptr<Command>> commands_;
std::vector<std::unique_ptr<Buffer>> buffers_;
std::vector<std::unique_ptr<Pipeline>> pipelines_;
+ std::vector<std::unique_ptr<type::Type>> types_;
std::vector<std::unique_ptr<Format>> formats_;
};
diff --git a/src/type.cc b/src/type.cc
new file mode 100644
index 0000000..f25e79f
--- /dev/null
+++ b/src/type.cc
@@ -0,0 +1,101 @@
+// Copyright 2019 The Amber Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/type.h"
+
+#include <cassert>
+#include <memory>
+
+#include "src/make_unique.h"
+
+namespace amber {
+namespace type {
+
+Type::Type() = default;
+
+Type::~Type() = default;
+
+List* Type::AsList() {
+ return static_cast<List*>(this);
+}
+
+Number* Type::AsNumber() {
+ return static_cast<Number*>(this);
+}
+
+Struct* Type::AsStruct() {
+ return static_cast<Struct*>(this);
+}
+
+const List* Type::AsList() const {
+ return static_cast<const List*>(this);
+}
+
+const Number* Type::AsNumber() const {
+ return static_cast<const Number*>(this);
+}
+
+const Struct* Type::AsStruct() const {
+ return static_cast<const Struct*>(this);
+}
+
+// static
+std::unique_ptr<Number> Number::Int(uint32_t bits) {
+ return MakeUnique<Number>(FormatMode::kSInt, bits);
+}
+
+// static
+std::unique_ptr<Number> Number::Uint(uint32_t bits) {
+ return MakeUnique<Number>(FormatMode::kUInt, bits);
+}
+
+// static
+std::unique_ptr<Number> Number::Float(uint32_t bits) {
+ return MakeUnique<Number>(FormatMode::kSFloat, bits);
+}
+
+Number::Number(FormatMode format_mode) : format_mode_(format_mode) {}
+
+Number::Number(FormatMode format_mode, uint32_t bits)
+ : format_mode_(format_mode), bits_(bits) {}
+
+Number::~Number() = default;
+
+List::List() = default;
+
+List::~List() = default;
+
+uint32_t List::SizeInBytes() const {
+ if (pack_size_in_bits_ > 0)
+ return pack_size_in_bits_;
+
+ uint32_t size = 0;
+ for (const auto& member : members_)
+ size += member.SizeInBytes();
+
+ return size;
+}
+
+Struct::Struct() = default;
+
+Struct::~Struct() = default;
+
+// Struct side is dependent on the layout we're currently in ....
+uint32_t Struct::SizeInBytes() const {
+ assert(false && "Not reached");
+ return 0;
+}
+
+} // namespace type
+} // namespace amber
diff --git a/src/type.h b/src/type.h
new file mode 100644
index 0000000..93aba68
--- /dev/null
+++ b/src/type.h
@@ -0,0 +1,298 @@
+// Copyright 2019 The Amber Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TYPE_H_
+#define SRC_TYPE_H_
+
+#include <cassert>
+#include <memory>
+#include <vector>
+
+#include "src/format_data.h"
+#include "src/make_unique.h"
+
+namespace amber {
+namespace type {
+
+class List;
+class Number;
+class Struct;
+
+class Type {
+ public:
+ Type();
+ virtual ~Type();
+
+ static bool IsSignedInt(FormatMode mode) {
+ return mode == FormatMode::kSInt || mode == FormatMode::kSNorm ||
+ mode == FormatMode::kSScaled;
+ }
+
+ static bool IsUnsignedInt(FormatMode mode) {
+ return mode == FormatMode::kUInt || mode == FormatMode::kUNorm ||
+ mode == FormatMode::kUScaled || mode == FormatMode::kSRGB;
+ }
+
+ static bool IsInt(FormatMode mode) {
+ return IsSignedInt(mode) || IsUnsignedInt(mode);
+ }
+
+ static bool IsFloat(FormatMode mode) {
+ return mode == FormatMode::kSFloat || mode == FormatMode::kUFloat;
+ }
+
+ static bool IsInt8(FormatMode mode, uint32_t num_bits) {
+ return IsSignedInt(mode) && num_bits == 8;
+ }
+ static bool IsInt16(FormatMode mode, uint32_t num_bits) {
+ return IsSignedInt(mode) && num_bits == 16;
+ }
+ static bool IsInt32(FormatMode mode, uint32_t num_bits) {
+ return IsSignedInt(mode) && num_bits == 32;
+ }
+ static bool IsInt64(FormatMode mode, uint32_t num_bits) {
+ return IsSignedInt(mode) && num_bits == 64;
+ }
+
+ static bool IsUint8(FormatMode mode, uint32_t num_bits) {
+ return IsUnsignedInt(mode) && num_bits == 8;
+ }
+ static bool IsUint16(FormatMode mode, uint32_t num_bits) {
+ return IsUnsignedInt(mode) && num_bits == 16;
+ }
+ static bool IsUint32(FormatMode mode, uint32_t num_bits) {
+ return IsUnsignedInt(mode) && num_bits == 32;
+ }
+ static bool IsUint64(FormatMode mode, uint32_t num_bits) {
+ return IsUnsignedInt(mode) && num_bits == 64;
+ }
+
+ static bool IsFloat16(FormatMode mode, uint32_t num_bits) {
+ return IsFloat(mode) && num_bits == 16;
+ }
+ static bool IsFloat32(FormatMode mode, uint32_t num_bits) {
+ return IsFloat(mode) && num_bits == 32;
+ }
+ static bool IsFloat64(FormatMode mode, uint32_t num_bits) {
+ return IsFloat(mode) && num_bits == 64;
+ }
+
+ // Returns the size in bytes of a single element of the type. This does not
+ // include space for arrays, vectors, etc.
+ virtual uint32_t SizeInBytes() const = 0;
+
+ virtual bool Equal(const Type* b) const = 0;
+
+ virtual bool IsList() const { return false; }
+ virtual bool IsNumber() const { return false; }
+ virtual bool IsStruct() const { return false; }
+
+ List* AsList();
+ Number* AsNumber();
+ Struct* AsStruct();
+
+ const List* AsList() const;
+ const Number* AsNumber() const;
+ const Struct* AsStruct() const;
+
+ void SetRowCount(uint32_t size) { row_count_ = size; }
+ uint32_t RowCount() const { return row_count_; }
+
+ void SetColumnCount(uint32_t size) { column_count_ = size; }
+ uint32_t ColumnCount() const { return column_count_; }
+
+ void SetIsRuntimeArray() { is_array_ = true; }
+ void SetIsSizedArray(uint32_t size) {
+ is_array_ = true;
+ array_size_ = size;
+ }
+ bool IsArray() const { return is_array_; }
+ bool IsSizedArray() const { return is_array_ && array_size_ > 0; }
+ bool IsRuntimeArray() const { return is_array_ && array_size_ == 0; }
+ uint32_t ArraySize() const { return array_size_; }
+
+ bool IsVec() const { return column_count_ == 1 && row_count_ > 1; }
+
+ // Returns true if this type holds a vec3.
+ bool IsVec3() const { return column_count_ == 1 && row_count_ == 3; }
+
+ // Returns true if this type holds a matrix.
+ bool IsMatrix() const { return column_count_ > 1 && row_count_ > 1; }
+
+ private:
+ uint32_t row_count_ = 1;
+ uint32_t column_count_ = 1;
+ uint32_t array_size_ = 0;
+ bool is_array_ = false;
+};
+
+class Number : public Type {
+ public:
+ explicit Number(FormatMode mode);
+ Number(FormatMode mode, uint32_t bits);
+ ~Number() override;
+
+ static std::unique_ptr<Number> Int(uint32_t bits);
+ static std::unique_ptr<Number> Uint(uint32_t bits);
+ static std::unique_ptr<Number> Float(uint32_t bits);
+
+ bool IsNumber() const override { return true; }
+
+ uint32_t NumBits() const { return bits_; }
+ uint32_t SizeInBytes() const override { return bits_ / 8; }
+
+ bool Equal(const Type* b) const override {
+ if (!b->IsNumber())
+ return false;
+
+ auto n = b->AsNumber();
+ return format_mode_ == n->format_mode_ && bits_ == n->bits_;
+ }
+
+ FormatMode GetFormatMode() const { return format_mode_; }
+
+ private:
+ FormatMode format_mode_ = FormatMode::kSInt;
+ uint32_t bits_ = 32;
+};
+
+// The list type only holds lists of scalar float and int values.
+class List : public Type {
+ public:
+ struct Member {
+ Member(FormatComponentType t, FormatMode m, uint32_t b)
+ : name(t), mode(m), num_bits(b) {}
+
+ uint32_t SizeInBytes() const { return num_bits / 8; }
+
+ FormatComponentType name = FormatComponentType::kR;
+ FormatMode mode = FormatMode::kSInt;
+ uint32_t num_bits = 0;
+ };
+
+ List();
+ ~List() override;
+
+ bool IsList() const override { return true; }
+
+ bool Equal(const Type* b) const override {
+ if (!b->IsList())
+ return false;
+
+ auto l = b->AsList();
+ if (pack_size_in_bits_ != l->pack_size_in_bits_)
+ return false;
+ if (members_.size() != l->members_.size())
+ return false;
+
+ auto& lm = l->Members();
+ for (size_t i = 0; i < members_.size(); ++i) {
+ if (members_[i].name != lm[i].name)
+ return false;
+ if (members_[i].mode != lm[i].mode)
+ return false;
+ if (members_[i].num_bits != lm[i].num_bits)
+ return false;
+ }
+ return true;
+ }
+
+ void SetPackSizeInBits(uint32_t size) { pack_size_in_bits_ = size; }
+ uint32_t PackSizeInBits() const { return pack_size_in_bits_; }
+ bool IsPacked() const { return pack_size_in_bits_ > 0; }
+
+ void AddMember(FormatComponentType name, FormatMode mode, uint32_t num_bits) {
+ members_.push_back({name, mode, num_bits});
+ }
+
+ const std::vector<Member>& Members() const { return members_; }
+ std::vector<Member>& Members() { return members_; }
+
+ uint32_t SizeInBytes() const override;
+
+ private:
+ std::vector<Member> members_;
+ uint32_t pack_size_in_bits_ = 0;
+};
+
+class Struct : public Type {
+ public:
+ struct Member {
+ Type* type;
+ int32_t offset_in_bytes = -1;
+ int32_t array_stride_in_bytes = -1;
+ int32_t matrix_stride_in_bytes = -1;
+
+ bool HasOffset() const { return offset_in_bytes >= 0; }
+ bool HasArrayStride() const { return array_stride_in_bytes > 0; }
+ bool HasMatrixStride() const { return matrix_stride_in_bytes > 0; }
+ };
+
+ Struct();
+ ~Struct() override;
+
+ uint32_t SizeInBytes() const override;
+ bool IsStruct() const override { return true; }
+
+ bool Equal(const Type* b) const override {
+ if (!b->IsStruct())
+ return false;
+
+ auto s = b->AsStruct();
+ if (is_stride_specified_ != s->is_stride_specified_)
+ return false;
+ if (stride_in_bytes_ != s->stride_in_bytes_)
+ return false;
+ if (members_.size() != s->members_.size())
+ return false;
+
+ auto& sm = s->Members();
+ for (size_t i = 0; i < members_.size(); ++i) {
+ if (members_[i].offset_in_bytes != sm[i].offset_in_bytes)
+ return false;
+ if (members_[i].array_stride_in_bytes != sm[i].array_stride_in_bytes)
+ return false;
+ if (members_[i].matrix_stride_in_bytes != sm[i].matrix_stride_in_bytes)
+ return false;
+ if (!members_[i].type->Equal(sm[i].type))
+ return false;
+ }
+ return true;
+ }
+
+ bool HasStride() const { return is_stride_specified_; }
+ uint32_t StrideInBytes() const { return stride_in_bytes_; }
+ void SetStrideInBytes(uint32_t stride) {
+ is_stride_specified_ = true;
+ stride_in_bytes_ = stride;
+ }
+
+ Member* AddMember(Type* type) {
+ members_.push_back({});
+ members_.back().type = type;
+ return &members_.back();
+ }
+
+ const std::vector<Member>& Members() const { return members_; }
+
+ private:
+ std::vector<Member> members_;
+ bool is_stride_specified_ = false;
+ uint32_t stride_in_bytes_ = 0;
+};
+
+} // namespace type
+} // namespace amber
+
+#endif // SRC_TYPE_H_
diff --git a/src/format_parser.cc b/src/type_parser.cc
index b0e51fb..a6779f0 100644
--- a/src/format_parser.cc
+++ b/src/type_parser.cc
@@ -12,20 +12,21 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "src/format_parser.h"
+#include "src/type_parser.h"
#include <cassert>
#include <cstdlib>
+#include <string>
#include "src/make_unique.h"
namespace amber {
-FormatParser::FormatParser() = default;
+TypeParser::TypeParser() = default;
-FormatParser::~FormatParser() = default;
+TypeParser::~TypeParser() = default;
-std::unique_ptr<Format> FormatParser::Parse(const std::string& data) {
+std::unique_ptr<type::Type> TypeParser::Parse(const std::string& data) {
if (data.empty())
return nullptr;
@@ -33,50 +34,60 @@ std::unique_ptr<Format> FormatParser::Parse(const std::string& data) {
if (data.find('/', 0) != std::string::npos)
return ParseGlslFormat(data);
- FormatType type = NameToType(data);
- if (type == FormatType::kUnknown)
- return nullptr;
+ // Walk the string backwards. This means we'll know if it's pack and we'll
+ // know the mode before we get to a given named component.
+ size_t cur_pos = std::string::npos;
+ for (;;) {
+ size_t next_pos = data.rfind('_', cur_pos);
+ if (next_pos == std::string::npos) {
+ if (cur_pos != std::string::npos)
+ ProcessChunk(data.substr(0, cur_pos + 1));
+ break;
+ }
- auto fmt = MakeUnique<Format>();
- fmt->SetFormatType(type);
+ ProcessChunk(data.substr(next_pos + 1, cur_pos - next_pos));
+ cur_pos = next_pos - 1;
+ }
- size_t cur_pos = 0;
- while (cur_pos < data.length()) {
- size_t next_pos = data.find('_', cur_pos);
- if (next_pos == std::string::npos)
- next_pos = data.length();
+ if (pieces_.empty())
+ return nullptr;
- ProcessChunk(fmt.get(), data.substr(cur_pos, next_pos - cur_pos).c_str());
- cur_pos = next_pos + 1;
+ std::unique_ptr<type::Type> type = nullptr;
+ if (pack_size_ == 0 && pieces_.size() == 1 &&
+ pieces_[0].type == FormatComponentType::kR) {
+ type = MakeUnique<type::Number>(pieces_[0].mode, pieces_[0].num_bits);
+ } else {
+ type = MakeUnique<type::List>();
+ type->SetRowCount(static_cast<uint32_t>(pieces_.size()));
+ type->AsList()->SetPackSizeInBits(pack_size_);
+
+ for (const auto& piece : pieces_)
+ type->AsList()->AddMember(piece.type, piece.mode, piece.num_bits);
}
- assert(pieces_.empty());
-
- return fmt;
-}
+ pack_size_ = 0;
+ mode_ = FormatMode::kSInt;
+ pieces_.clear();
-void FormatParser::AddPiece(FormatComponentType type, uint8_t bits) {
- pieces_.emplace_back(type, bits);
+ return type;
}
-void FormatParser::FlushPieces(Format* fmt, FormatMode mode) {
- for (const auto& piece : pieces_)
- fmt->AddComponent(piece.type, mode, piece.num_bits);
-
- pieces_.clear();
+void TypeParser::AddPiece(FormatComponentType type,
+ FormatMode mode,
+ uint8_t bits) {
+ pieces_.insert(pieces_.begin(), Pieces{type, mode, bits});
}
-// TODO(dsinclair): Remove asserts return something ...?
-void FormatParser::ProcessChunk(Format* fmt, const std::string& data) {
+void TypeParser::ProcessChunk(const std::string& data) {
assert(data.size() > 0);
if (data[0] == 'P') {
if (data == "PACK8")
- fmt->SetPackSize(8);
+ pack_size_ = 8;
else if (data == "PACK16")
- fmt->SetPackSize(16);
+ pack_size_ = 16;
else if (data == "PACK32")
- fmt->SetPackSize(32);
+ pack_size_ = 32;
else
assert(false);
@@ -85,13 +96,13 @@ void FormatParser::ProcessChunk(Format* fmt, const std::string& data) {
if (data[0] == 'U') {
if (data == "UINT")
- FlushPieces(fmt, FormatMode::kUInt);
+ mode_ = FormatMode::kUInt;
else if (data == "UNORM")
- FlushPieces(fmt, FormatMode::kUNorm);
+ mode_ = FormatMode::kUNorm;
else if (data == "UFLOAT")
- FlushPieces(fmt, FormatMode::kUFloat);
+ mode_ = FormatMode::kUFloat;
else if (data == "USCALED")
- FlushPieces(fmt, FormatMode::kUScaled);
+ mode_ = FormatMode::kUScaled;
else
assert(false);
@@ -100,63 +111,66 @@ void FormatParser::ProcessChunk(Format* fmt, const std::string& data) {
if (data[0] == 'S') {
if (data == "SINT")
- FlushPieces(fmt, FormatMode::kSInt);
+ mode_ = FormatMode::kSInt;
else if (data == "SNORM")
- FlushPieces(fmt, FormatMode::kSNorm);
+ mode_ = FormatMode::kSNorm;
else if (data == "SSCALED")
- FlushPieces(fmt, FormatMode::kSScaled);
+ mode_ = FormatMode::kSScaled;
else if (data == "SFLOAT")
- FlushPieces(fmt, FormatMode::kSFloat);
+ mode_ = FormatMode::kSFloat;
else if (data == "SRGB")
- FlushPieces(fmt, FormatMode::kSRGB);
+ mode_ = FormatMode::kSRGB;
else if (data == "S8")
- AddPiece(FormatComponentType::kS, 8);
+ AddPiece(FormatComponentType::kS, mode_, 8);
else
assert(false);
return;
}
- size_t cur_pos = 0;
- while (cur_pos < data.size()) {
+ int32_t cur_pos = static_cast<int32_t>(data.size()) - 1;
+ for (;;) {
FormatComponentType type = FormatComponentType::kA;
- switch (data[cur_pos++]) {
- case 'X':
+ while (cur_pos >= 0) {
+ if (data[static_cast<size_t>(cur_pos)] == 'X') {
type = FormatComponentType::kX;
break;
- case 'D':
+ } else if (data[static_cast<size_t>(cur_pos)] == 'D') {
type = FormatComponentType::kD;
break;
- case 'R':
+ } else if (data[static_cast<size_t>(cur_pos)] == 'R') {
type = FormatComponentType::kR;
break;
- case 'G':
+ } else if (data[static_cast<size_t>(cur_pos)] == 'G') {
type = FormatComponentType::kG;
break;
- case 'B':
+ } else if (data[static_cast<size_t>(cur_pos)] == 'B') {
type = FormatComponentType::kB;
break;
- case 'A':
+ } else if (data[static_cast<size_t>(cur_pos)] == 'A') {
type = FormatComponentType::kA;
break;
- default:
- assert(false);
+ }
+ --cur_pos;
}
-
- assert(cur_pos < data.size());
+ assert(cur_pos >= 0);
char* next_str;
- const char* str = data.c_str() + cur_pos;
+ const char* str = data.c_str() + cur_pos + 1;
uint64_t val = static_cast<uint64_t>(std::strtol(str, &next_str, 10));
- AddPiece(type, static_cast<uint8_t>(val));
+ if (val > 0)
+ AddPiece(type, mode_, static_cast<uint8_t>(val));
+
+ if (cur_pos == 0)
+ break;
- cur_pos += static_cast<size_t>(next_str - str);
+ --cur_pos;
}
}
// static
-FormatType FormatParser::NameToType(const std::string& data) {
+FormatType TypeParser::NameToFormatType(const std::string& data) {
if (data == "A1R5G5B5_UNORM_PACK16")
return FormatType::kA1R5G5B5_UNORM_PACK16;
if (data == "A2B10G10R10_SINT_PACK32")
@@ -419,7 +433,8 @@ FormatType FormatParser::NameToType(const std::string& data) {
return FormatType::kUnknown;
}
-std::unique_ptr<Format> FormatParser::ParseGlslFormat(const std::string& fmt) {
+std::unique_ptr<type::Type> TypeParser::ParseGlslFormat(
+ const std::string& fmt) {
size_t pos = fmt.find('/');
std::string gl_type = fmt.substr(0, pos);
std::string glsl_type = fmt.substr(pos + 1);
diff --git a/src/type_parser.h b/src/type_parser.h
new file mode 100644
index 0000000..d737e86
--- /dev/null
+++ b/src/type_parser.h
@@ -0,0 +1,64 @@
+// Copyright 2019 The Amber Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TYPE_PARSER_H_
+#define SRC_TYPE_PARSER_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "src/type.h"
+
+namespace amber {
+
+/// Parses a Vulkan image string into a type object.
+class TypeParser {
+ public:
+ static FormatType NameToFormatType(const std::string& data);
+
+ TypeParser();
+ ~TypeParser();
+
+ /// Parses the |fmt| string and returns the associated type, nullptr if the
+ /// conversion is not possible.
+ ///
+ /// The format string can come in two different forms, it can be a vulkan
+ /// style format string (e.g. R32G32B32A32_SFLOAT) or it can be in the type
+ /// format (gl_type/glsl_type) specified by VkScript (e.g. byte/vec4).
+ std::unique_ptr<type::Type> Parse(const std::string& fmt);
+
+ private:
+ std::unique_ptr<type::Type> ParseGlslFormat(const std::string& fmt);
+ void ProcessChunk(const std::string&);
+ void AddPiece(FormatComponentType type, FormatMode mode, uint8_t bits);
+ void FlushPieces(type::Type* type, FormatMode mode);
+
+ struct Pieces {
+ Pieces(FormatComponentType t, FormatMode m, uint8_t bits)
+ : type(t), mode(m), num_bits(bits) {}
+
+ FormatComponentType type;
+ FormatMode mode;
+ uint8_t num_bits;
+ };
+
+ FormatMode mode_ = FormatMode::kSInt;
+ uint32_t pack_size_ = 0;
+ std::vector<Pieces> pieces_;
+};
+
+} // namespace amber
+
+#endif // SRC_TYPE_PARSER_H_
diff --git a/src/format_parser_test.cc b/src/type_parser_test.cc
index bb42553..c26c329 100644
--- a/src/format_parser_test.cc
+++ b/src/type_parser_test.cc
@@ -12,15 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "src/format_parser.h"
+#include "src/type_parser.h"
#include "gtest/gtest.h"
+#include "src/format.h"
namespace amber {
-using FormatParserTest = testing::Test;
+using TypeParserTest = testing::Test;
-TEST_F(FormatParserTest, Formats) {
+TEST_F(TypeParserTest, Formats) {
struct {
const char* name;
FormatType type;
@@ -1175,71 +1176,77 @@ TEST_F(FormatParserTest, Formats) {
}},
};
- for (const auto& fmt : formats) {
- FormatParser parser;
- auto format = parser.Parse(fmt.name);
+ for (const auto& data : formats) {
+ TypeParser parser;
+ auto type = parser.Parse(data.name);
- ASSERT_TRUE(format != nullptr) << fmt.name;
- EXPECT_EQ(fmt.type, format->GetFormatType()) << fmt.name;
- EXPECT_EQ(fmt.pack_size, format->GetPackSize()) << fmt.name;
+ ASSERT_TRUE(type != nullptr) << data.name;
- auto& segs = format->GetSegments();
- ASSERT_TRUE(fmt.component_count <= segs.size()) << fmt.name;
+ Format fmt(type.get());
+ EXPECT_EQ(data.type, fmt.GetFormatType()) << data.name;
+ if (data.pack_size > 0) {
+ ASSERT_TRUE(fmt.GetType()->IsList());
+ ASSERT_TRUE(fmt.GetType()->AsList()->IsPacked());
+ EXPECT_EQ(data.pack_size, fmt.GetType()->AsList()->PackSizeInBits());
- for (size_t i = 0; i < fmt.component_count; ++i) {
- EXPECT_EQ(fmt.components[i].type, segs[i].GetComponent()->type)
- << fmt.name;
- EXPECT_EQ(fmt.components[i].mode, segs[i].GetComponent()->mode)
- << fmt.name;
- EXPECT_EQ(fmt.components[i].num_bits, segs[i].GetComponent()->num_bits)
- << fmt.name;
- }
+ const auto& members = fmt.GetType()->AsList()->Members();
+ for (size_t i = 0; i < data.component_count; ++i) {
+ EXPECT_EQ(data.components[i].type, members[i].name) << data.name;
+ EXPECT_EQ(data.components[i].mode, members[i].mode) << data.name;
+ EXPECT_EQ(data.components[i].num_bits, members[i].num_bits)
+ << data.name;
+ }
+ } else {
+ auto& segs = fmt.GetSegments();
+ ASSERT_TRUE(data.component_count <= segs.size()) << data.name;
+
+ for (size_t i = 0; i < data.component_count; ++i) {
+ EXPECT_EQ(data.components[i].mode, segs[i].GetFormatMode());
+ EXPECT_EQ(data.components[i].num_bits, segs[i].GetNumBits())
+ << data.name;
+ }
- if (fmt.component_count < segs.size()) {
- // Only one padding added
- EXPECT_EQ(1, segs.size() - fmt.component_count);
- EXPECT_TRUE(segs.back().IsPadding());
+ if (data.component_count < segs.size()) {
+ // Only one padding added
+ EXPECT_EQ(1, segs.size() - data.component_count);
+ EXPECT_TRUE(segs.back().IsPadding());
+ }
}
}
} // NOLINT(readability/fn_size)
-TEST_F(FormatParserTest, InvalidFormat) {
- FormatParser parser;
- auto format = parser.Parse("BLAH_BLAH_BLAH");
- EXPECT_TRUE(format == nullptr);
+TEST_F(TypeParserTest, InvalidFormat) {
+ TypeParser parser;
+ auto type = parser.Parse("BLAH_BLAH_BLAH");
+ EXPECT_TRUE(type == nullptr);
}
-TEST_F(FormatParserTest, EmptyFormat) {
- FormatParser parser;
- auto format = parser.Parse("");
- EXPECT_TRUE(format == nullptr);
+TEST_F(TypeParserTest, EmptyFormat) {
+ TypeParser parser;
+ auto type = parser.Parse("");
+ EXPECT_TRUE(type == nullptr);
}
-TEST_F(FormatParserTest, GlslString) {
- FormatParser parser;
- auto format = parser.Parse("float/vec3");
- ASSERT_TRUE(format != nullptr);
+TEST_F(TypeParserTest, GlslString) {
+ TypeParser parser;
+ auto type = parser.Parse("float/vec3");
+ ASSERT_TRUE(type != nullptr);
- EXPECT_EQ(FormatType::kR32G32B32_SFLOAT, format->GetFormatType());
- EXPECT_EQ(static_cast<size_t>(0U), format->GetPackSize());
+ Format fmt(type.get());
+ EXPECT_EQ(FormatType::kR32G32B32_SFLOAT, fmt.GetFormatType());
- auto& segs = format->GetSegments();
+ auto& segs = fmt.GetSegments();
ASSERT_EQ(4U, segs.size());
- EXPECT_EQ(FormatComponentType::kR, segs[0].GetComponent()->type);
- EXPECT_EQ(FormatMode::kSFloat, segs[0].GetComponent()->mode);
- EXPECT_EQ(32U, segs[0].GetComponent()->num_bits);
- EXPECT_EQ(FormatComponentType::kG, segs[1].GetComponent()->type);
- EXPECT_EQ(FormatMode::kSFloat, segs[1].GetComponent()->mode);
- EXPECT_EQ(32U, segs[1].GetComponent()->num_bits);
- EXPECT_EQ(FormatComponentType::kB, segs[2].GetComponent()->type);
- EXPECT_EQ(FormatMode::kSFloat, segs[2].GetComponent()->mode);
- EXPECT_EQ(32U, segs[2].GetComponent()->num_bits);
+ for (size_t i = 0; i < 3; ++i) {
+ EXPECT_TRUE(
+ type::Type::IsFloat32(segs[i].GetFormatMode(), segs[i].GetNumBits()));
+ }
EXPECT_TRUE(segs[3].IsPadding());
}
-TEST_F(FormatParserTest, GlslStrings) {
+TEST_F(TypeParserTest, GlslStrings) {
struct {
const char* name;
FormatType type;
@@ -1260,15 +1267,16 @@ TEST_F(FormatParserTest, GlslStrings) {
};
for (const auto& str : strs) {
- FormatParser parser;
- auto format = parser.Parse(str.name);
- ASSERT_FALSE(format == nullptr);
+ TypeParser parser;
+ auto type = parser.Parse(str.name);
+ ASSERT_FALSE(type == nullptr);
- EXPECT_EQ(str.type, format->GetFormatType()) << str.name;
+ Format fmt(type.get());
+ EXPECT_EQ(str.type, fmt.GetFormatType()) << str.name;
}
}
-TEST_F(FormatParserTest, GlslStringInvalid) {
+TEST_F(TypeParserTest, GlslStringInvalid) {
struct {
const char* name;
} strs[] = {
@@ -1279,9 +1287,9 @@ TEST_F(FormatParserTest, GlslStringInvalid) {
};
for (const auto& str : strs) {
- FormatParser parser;
- auto format = parser.Parse(str.name);
- EXPECT_TRUE(format == nullptr);
+ TypeParser parser;
+ auto fmt = parser.Parse(str.name);
+ EXPECT_TRUE(fmt == nullptr);
}
}
diff --git a/src/type_test.cc b/src/type_test.cc
new file mode 100644
index 0000000..bc140d4
--- /dev/null
+++ b/src/type_test.cc
@@ -0,0 +1,399 @@
+// Copyright 2019 The Amber Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/type.h"
+
+#include "gtest/gtest.h"
+
+namespace amber {
+namespace type {
+
+using TypeTest = testing::Test;
+
+TEST_F(TypeTest, IsArray) {
+ Number i(FormatMode::kSInt, 16);
+
+ EXPECT_FALSE(i.IsArray());
+ EXPECT_FALSE(i.IsRuntimeArray());
+ EXPECT_FALSE(i.IsSizedArray());
+
+ i.SetIsRuntimeArray();
+ EXPECT_TRUE(i.IsArray());
+ EXPECT_TRUE(i.IsRuntimeArray());
+ EXPECT_FALSE(i.IsSizedArray());
+
+ i.SetIsSizedArray(3);
+ EXPECT_TRUE(i.IsArray());
+ EXPECT_FALSE(i.IsRuntimeArray());
+ EXPECT_TRUE(i.IsSizedArray());
+ EXPECT_EQ(3, i.ArraySize());
+}
+
+TEST_F(TypeTest, IsStruct) {
+ EXPECT_FALSE(Number(FormatMode::kSInt).IsStruct());
+ EXPECT_TRUE(Struct().IsStruct());
+ EXPECT_FALSE(List().IsStruct());
+}
+
+TEST_F(TypeTest, IsNumber) {
+ EXPECT_TRUE(Number(FormatMode::kSInt).IsNumber());
+ EXPECT_FALSE(Struct().IsNumber());
+ EXPECT_FALSE(List().IsNumber());
+}
+
+TEST_F(TypeTest, IsList) {
+ EXPECT_FALSE(Number(FormatMode::kSInt).IsList());
+ EXPECT_FALSE(Struct().IsList());
+ EXPECT_TRUE(List().IsList());
+}
+
+TEST_F(TypeTest, Vectors) {
+ Number i(FormatMode::kSInt, 16);
+ i.SetRowCount(2);
+
+ EXPECT_EQ(2, i.RowCount());
+ EXPECT_TRUE(i.IsVec());
+ EXPECT_FALSE(i.IsVec3());
+ EXPECT_FALSE(i.IsMatrix());
+
+ i.SetColumnCount(3);
+ EXPECT_FALSE(i.IsVec3());
+}
+
+TEST_F(TypeTest, Matrix) {
+ Number i(FormatMode::kSInt, 16);
+ i.SetColumnCount(2);
+ i.SetRowCount(2);
+
+ EXPECT_EQ(2, i.ColumnCount());
+ EXPECT_EQ(2, i.RowCount());
+
+ EXPECT_FALSE(i.IsVec());
+ EXPECT_TRUE(i.IsMatrix());
+}
+
+TEST_F(TypeTest, SizeInBytesForVector) {
+ Number i(FormatMode::kSInt, 32);
+ uint32_t bytes = i.SizeInBytes();
+
+ i.SetRowCount(3);
+ EXPECT_EQ(bytes, i.SizeInBytes());
+}
+
+TEST_F(TypeTest, SizeInBytesForMatrix) {
+ Number i(FormatMode::kSInt, 32);
+ uint32_t bytes = i.SizeInBytes();
+
+ i.SetColumnCount(3);
+ i.SetRowCount(3);
+ EXPECT_EQ(bytes, i.SizeInBytes());
+}
+
+TEST_F(TypeTest, SizeInBytesForArray) {
+ Number i(FormatMode::kSInt, 32);
+ uint32_t bytes = i.SizeInBytes();
+
+ i.SetIsSizedArray(3);
+ EXPECT_EQ(bytes, i.SizeInBytes());
+}
+
+TEST_F(TypeTest, NumberEqual) {
+ Number n1(FormatMode::kSFloat, 32);
+ Number n2(FormatMode::kSFloat, 32);
+ Number n3(FormatMode::kSFloat, 16);
+ Number n4(FormatMode::kSInt, 32);
+
+ List l;
+ Struct s;
+
+ EXPECT_TRUE(n1.Equal(&n2));
+ EXPECT_FALSE(n1.Equal(&n3));
+ EXPECT_FALSE(n1.Equal(&n4));
+ EXPECT_FALSE(n1.Equal(&l));
+ EXPECT_FALSE(n1.Equal(&s));
+}
+
+TEST_F(TypeTest, ListPacked) {
+ List l;
+ EXPECT_FALSE(l.IsPacked());
+ EXPECT_EQ(0U, l.PackSizeInBits());
+
+ l.SetPackSizeInBits(32);
+ EXPECT_TRUE(l.IsPacked());
+ EXPECT_EQ(32U, l.PackSizeInBits());
+}
+
+TEST_F(TypeTest, ListEqual) {
+ List l1;
+ List l2;
+
+ l1.AddMember(FormatComponentType::kR, FormatMode::kSFloat, 32);
+ l2.AddMember(FormatComponentType::kR, FormatMode::kSFloat, 32);
+ EXPECT_TRUE(l1.Equal(&l2));
+
+ l2.SetPackSizeInBits(24);
+ EXPECT_FALSE(l1.Equal(&l2));
+
+ List l3;
+ l3.AddMember(FormatComponentType::kR, FormatMode::kSFloat, 16);
+ EXPECT_FALSE(l1.Equal(&l3));
+
+ List l4;
+ l4.AddMember(FormatComponentType::kR, FormatMode::kSInt, 16);
+ EXPECT_FALSE(l1.Equal(&l4));
+
+ List l5;
+ l5.AddMember(FormatComponentType::kG, FormatMode::kSFloat, 32);
+ EXPECT_FALSE(l1.Equal(&l5));
+
+ List l6;
+ l6.AddMember(FormatComponentType::kR, FormatMode::kSFloat, 32);
+ l6.AddMember(FormatComponentType::kG, FormatMode::kSFloat, 32);
+ EXPECT_FALSE(l1.Equal(&l6));
+}
+
+TEST_F(TypeTest, StructStride) {
+ Struct s;
+ EXPECT_FALSE(s.HasStride());
+ EXPECT_EQ(0U, s.StrideInBytes());
+
+ s.SetStrideInBytes(32);
+ EXPECT_TRUE(s.HasStride());
+ EXPECT_EQ(32U, s.StrideInBytes());
+}
+
+TEST_F(TypeTest, StructEqual) {
+ Struct s1;
+ Struct s2;
+
+ auto num32 = Number::Float(32);
+ auto m1 = s1.AddMember(num32.get());
+ s2.AddMember(num32.get());
+ EXPECT_TRUE(s1.Equal(&s2));
+
+ s2.SetStrideInBytes(20);
+ EXPECT_FALSE(s1.Equal(&s2));
+
+ Struct s3;
+ auto num16 = Number::Float(16);
+ s3.AddMember(num16.get());
+ EXPECT_FALSE(s1.Equal(&s3));
+
+ Struct s4;
+ auto m = s4.AddMember(num16.get());
+ m->offset_in_bytes = 20;
+ EXPECT_FALSE(s1.Equal(&s4));
+
+ m->offset_in_bytes = m1->offset_in_bytes;
+ m->array_stride_in_bytes = 20;
+ EXPECT_FALSE(s1.Equal(&s4));
+
+ m->array_stride_in_bytes = m1->array_stride_in_bytes;
+ m->matrix_stride_in_bytes = 20;
+ EXPECT_FALSE(s1.Equal(&s4));
+}
+
+TEST_F(TypeTest, NumberDefault32Bits) {
+ EXPECT_EQ(4, Number(FormatMode::kUNorm).SizeInBytes());
+}
+
+TEST_F(TypeTest, NumberInBytes) {
+ EXPECT_EQ(1, Number(FormatMode::kSInt, 8).SizeInBytes());
+ EXPECT_EQ(2, Number(FormatMode::kSInt, 16).SizeInBytes());
+ EXPECT_EQ(4, Number(FormatMode::kSInt, 32).SizeInBytes());
+ EXPECT_EQ(8, Number(FormatMode::kSInt, 64).SizeInBytes());
+}
+
+TEST_F(TypeTest, IsInt) {
+ EXPECT_TRUE(Type::IsInt(FormatMode::kSInt));
+ EXPECT_TRUE(Type::IsInt(FormatMode::kSNorm));
+ EXPECT_TRUE(Type::IsInt(FormatMode::kSScaled));
+ EXPECT_TRUE(Type::IsInt(FormatMode::kSRGB));
+ EXPECT_TRUE(Type::IsInt(FormatMode::kUNorm));
+ EXPECT_TRUE(Type::IsInt(FormatMode::kUInt));
+ EXPECT_TRUE(Type::IsInt(FormatMode::kUScaled));
+ EXPECT_FALSE(Type::IsInt(FormatMode::kSFloat));
+ EXPECT_FALSE(Type::IsInt(FormatMode::kUFloat));
+}
+
+TEST_F(TypeTest, IsSignedInt) {
+ EXPECT_TRUE(Type::IsSignedInt(FormatMode::kSInt));
+ EXPECT_TRUE(Type::IsSignedInt(FormatMode::kSNorm));
+ EXPECT_TRUE(Type::IsSignedInt(FormatMode::kSScaled));
+ EXPECT_FALSE(Type::IsSignedInt(FormatMode::kSRGB));
+ EXPECT_FALSE(Type::IsSignedInt(FormatMode::kUNorm));
+ EXPECT_FALSE(Type::IsSignedInt(FormatMode::kUInt));
+ EXPECT_FALSE(Type::IsSignedInt(FormatMode::kUScaled));
+ EXPECT_FALSE(Type::IsSignedInt(FormatMode::kSFloat));
+ EXPECT_FALSE(Type::IsSignedInt(FormatMode::kUFloat));
+}
+
+TEST_F(TypeTest, IsUnsignedInt) {
+ EXPECT_FALSE(Type::IsUnsignedInt(FormatMode::kSInt));
+ EXPECT_FALSE(Type::IsUnsignedInt(FormatMode::kSNorm));
+ EXPECT_FALSE(Type::IsUnsignedInt(FormatMode::kSScaled));
+ EXPECT_TRUE(Type::IsUnsignedInt(FormatMode::kSRGB));
+ EXPECT_TRUE(Type::IsUnsignedInt(FormatMode::kUNorm));
+ EXPECT_TRUE(Type::IsUnsignedInt(FormatMode::kUInt));
+ EXPECT_TRUE(Type::IsUnsignedInt(FormatMode::kUScaled));
+ EXPECT_FALSE(Type::IsUnsignedInt(FormatMode::kSFloat));
+ EXPECT_FALSE(Type::IsUnsignedInt(FormatMode::kUFloat));
+}
+
+TEST_F(TypeTest, IsFloat) {
+ EXPECT_FALSE(Type::IsFloat(FormatMode::kSInt));
+ EXPECT_FALSE(Type::IsFloat(FormatMode::kSNorm));
+ EXPECT_FALSE(Type::IsFloat(FormatMode::kSScaled));
+ EXPECT_FALSE(Type::IsFloat(FormatMode::kSRGB));
+ EXPECT_FALSE(Type::IsFloat(FormatMode::kUNorm));
+ EXPECT_FALSE(Type::IsFloat(FormatMode::kUInt));
+ EXPECT_FALSE(Type::IsFloat(FormatMode::kUScaled));
+ EXPECT_TRUE(Type::IsFloat(FormatMode::kSFloat));
+ EXPECT_TRUE(Type::IsFloat(FormatMode::kUFloat));
+}
+
+TEST_F(TypeTest, IsInt8) {
+ EXPECT_TRUE(Type::IsInt8(FormatMode::kSInt, 8));
+ EXPECT_TRUE(Type::IsInt8(FormatMode::kSNorm, 8));
+ EXPECT_TRUE(Type::IsInt8(FormatMode::kSScaled, 8));
+ EXPECT_FALSE(Type::IsInt8(FormatMode::kSRGB, 8));
+ EXPECT_FALSE(Type::IsInt8(FormatMode::kUNorm, 8));
+ EXPECT_FALSE(Type::IsInt8(FormatMode::kUInt, 8));
+ EXPECT_FALSE(Type::IsInt8(FormatMode::kUScaled, 8));
+ EXPECT_FALSE(Type::IsInt8(FormatMode::kUFloat, 8));
+ EXPECT_FALSE(Type::IsInt8(FormatMode::kSFloat, 8));
+}
+
+TEST_F(TypeTest, IsInt16) {
+ EXPECT_TRUE(Type::IsInt16(FormatMode::kSInt, 16));
+ EXPECT_TRUE(Type::IsInt16(FormatMode::kSNorm, 16));
+ EXPECT_TRUE(Type::IsInt16(FormatMode::kSScaled, 16));
+ EXPECT_FALSE(Type::IsInt16(FormatMode::kSRGB, 16));
+ EXPECT_FALSE(Type::IsInt16(FormatMode::kUNorm, 16));
+ EXPECT_FALSE(Type::IsInt16(FormatMode::kUInt, 16));
+ EXPECT_FALSE(Type::IsInt16(FormatMode::kUScaled, 16));
+ EXPECT_FALSE(Type::IsInt16(FormatMode::kUFloat, 16));
+ EXPECT_FALSE(Type::IsInt16(FormatMode::kSFloat, 16));
+}
+
+TEST_F(TypeTest, IsInt32) {
+ EXPECT_TRUE(Type::IsInt32(FormatMode::kSInt, 32));
+ EXPECT_TRUE(Type::IsInt32(FormatMode::kSNorm, 32));
+ EXPECT_TRUE(Type::IsInt32(FormatMode::kSScaled, 32));
+ EXPECT_FALSE(Type::IsInt32(FormatMode::kSRGB, 32));
+ EXPECT_FALSE(Type::IsInt32(FormatMode::kUNorm, 32));
+ EXPECT_FALSE(Type::IsInt32(FormatMode::kUInt, 32));
+ EXPECT_FALSE(Type::IsInt32(FormatMode::kUScaled, 32));
+ EXPECT_FALSE(Type::IsInt32(FormatMode::kUFloat, 32));
+ EXPECT_FALSE(Type::IsInt32(FormatMode::kSFloat, 32));
+}
+
+TEST_F(TypeTest, IsInt64) {
+ EXPECT_TRUE(Type::IsInt64(FormatMode::kSInt, 64));
+ EXPECT_TRUE(Type::IsInt64(FormatMode::kSNorm, 64));
+ EXPECT_TRUE(Type::IsInt64(FormatMode::kSScaled, 64));
+ EXPECT_FALSE(Type::IsInt64(FormatMode::kSRGB, 64));
+ EXPECT_FALSE(Type::IsInt64(FormatMode::kUNorm, 64));
+ EXPECT_FALSE(Type::IsInt64(FormatMode::kUInt, 64));
+ EXPECT_FALSE(Type::IsInt64(FormatMode::kUScaled, 64));
+ EXPECT_FALSE(Type::IsInt64(FormatMode::kUFloat, 64));
+ EXPECT_FALSE(Type::IsInt64(FormatMode::kSFloat, 64));
+}
+
+TEST_F(TypeTest, IsUint8) {
+ EXPECT_FALSE(Type::IsUint8(FormatMode::kSInt, 8));
+ EXPECT_FALSE(Type::IsUint8(FormatMode::kSNorm, 8));
+ EXPECT_FALSE(Type::IsUint8(FormatMode::kSScaled, 8));
+ EXPECT_TRUE(Type::IsUint8(FormatMode::kSRGB, 8));
+ EXPECT_TRUE(Type::IsUint8(FormatMode::kUNorm, 8));
+ EXPECT_TRUE(Type::IsUint8(FormatMode::kUInt, 8));
+ EXPECT_TRUE(Type::IsUint8(FormatMode::kUScaled, 8));
+ EXPECT_FALSE(Type::IsUint8(FormatMode::kUFloat, 8));
+ EXPECT_FALSE(Type::IsUint8(FormatMode::kSFloat, 8));
+}
+
+TEST_F(TypeTest, IsUint16) {
+ EXPECT_FALSE(Type::IsUint16(FormatMode::kSInt, 16));
+ EXPECT_FALSE(Type::IsUint16(FormatMode::kSNorm, 16));
+ EXPECT_FALSE(Type::IsUint16(FormatMode::kSScaled, 16));
+ EXPECT_TRUE(Type::IsUint16(FormatMode::kSRGB, 16));
+ EXPECT_TRUE(Type::IsUint16(FormatMode::kUNorm, 16));
+ EXPECT_TRUE(Type::IsUint16(FormatMode::kUInt, 16));
+ EXPECT_TRUE(Type::IsUint16(FormatMode::kUScaled, 16));
+ EXPECT_FALSE(Type::IsUint16(FormatMode::kUFloat, 16));
+ EXPECT_FALSE(Type::IsUint16(FormatMode::kSFloat, 16));
+}
+
+TEST_F(TypeTest, IsUint32) {
+ EXPECT_FALSE(Type::IsUint32(FormatMode::kSInt, 32));
+ EXPECT_FALSE(Type::IsUint32(FormatMode::kSNorm, 32));
+ EXPECT_FALSE(Type::IsUint32(FormatMode::kSScaled, 32));
+ EXPECT_TRUE(Type::IsUint32(FormatMode::kSRGB, 32));
+ EXPECT_TRUE(Type::IsUint32(FormatMode::kUNorm, 32));
+ EXPECT_TRUE(Type::IsUint32(FormatMode::kUInt, 32));
+ EXPECT_TRUE(Type::IsUint32(FormatMode::kUScaled, 32));
+ EXPECT_FALSE(Type::IsUint32(FormatMode::kUFloat, 32));
+ EXPECT_FALSE(Type::IsUint32(FormatMode::kSFloat, 32));
+}
+
+TEST_F(TypeTest, IsUint64) {
+ EXPECT_FALSE(Type::IsUint64(FormatMode::kSInt, 64));
+ EXPECT_FALSE(Type::IsUint64(FormatMode::kSNorm, 64));
+ EXPECT_FALSE(Type::IsUint64(FormatMode::kSScaled, 64));
+ EXPECT_TRUE(Type::IsUint64(FormatMode::kSRGB, 64));
+ EXPECT_TRUE(Type::IsUint64(FormatMode::kUNorm, 64));
+ EXPECT_TRUE(Type::IsUint64(FormatMode::kUInt, 64));
+ EXPECT_TRUE(Type::IsUint64(FormatMode::kUScaled, 64));
+ EXPECT_FALSE(Type::IsUint64(FormatMode::kUFloat, 64));
+ EXPECT_FALSE(Type::IsUint64(FormatMode::kSFloat, 64));
+}
+
+TEST_F(TypeTest, IsFloat16) {
+ EXPECT_TRUE(Type::IsFloat16(FormatMode::kSFloat, 16));
+ EXPECT_TRUE(Type::IsFloat16(FormatMode::kUFloat, 16));
+ EXPECT_FALSE(Type::IsFloat16(FormatMode::kSInt, 16));
+ EXPECT_FALSE(Type::IsFloat16(FormatMode::kSNorm, 16));
+ EXPECT_FALSE(Type::IsFloat16(FormatMode::kSScaled, 16));
+ EXPECT_FALSE(Type::IsFloat16(FormatMode::kSRGB, 16));
+ EXPECT_FALSE(Type::IsFloat16(FormatMode::kUNorm, 16));
+ EXPECT_FALSE(Type::IsFloat16(FormatMode::kUInt, 16));
+ EXPECT_FALSE(Type::IsFloat16(FormatMode::kUScaled, 16));
+}
+
+TEST_F(TypeTest, IsFloat32) {
+ EXPECT_TRUE(Type::IsFloat32(FormatMode::kSFloat, 32));
+ EXPECT_TRUE(Type::IsFloat32(FormatMode::kUFloat, 32));
+ EXPECT_FALSE(Type::IsFloat32(FormatMode::kSInt, 32));
+ EXPECT_FALSE(Type::IsFloat32(FormatMode::kSNorm, 32));
+ EXPECT_FALSE(Type::IsFloat32(FormatMode::kSScaled, 32));
+ EXPECT_FALSE(Type::IsFloat32(FormatMode::kSRGB, 32));
+ EXPECT_FALSE(Type::IsFloat32(FormatMode::kUNorm, 32));
+ EXPECT_FALSE(Type::IsFloat32(FormatMode::kUInt, 32));
+ EXPECT_FALSE(Type::IsFloat32(FormatMode::kUScaled, 32));
+}
+
+TEST_F(TypeTest, IsFloat64) {
+ EXPECT_TRUE(Type::IsFloat64(FormatMode::kSFloat, 64));
+ EXPECT_TRUE(Type::IsFloat64(FormatMode::kUFloat, 64));
+ EXPECT_FALSE(Type::IsFloat64(FormatMode::kSInt, 64));
+ EXPECT_FALSE(Type::IsFloat64(FormatMode::kSNorm, 64));
+ EXPECT_FALSE(Type::IsFloat64(FormatMode::kSScaled, 64));
+ EXPECT_FALSE(Type::IsFloat64(FormatMode::kSRGB, 64));
+ EXPECT_FALSE(Type::IsFloat64(FormatMode::kUNorm, 64));
+ EXPECT_FALSE(Type::IsFloat64(FormatMode::kUInt, 64));
+ EXPECT_FALSE(Type::IsFloat64(FormatMode::kUScaled, 64));
+}
+
+} // namespace type
+} // namespace amber
diff --git a/src/verifier.cc b/src/verifier.cc
index cfa594f..ff4e288 100644
--- a/src/verifier.cc
+++ b/src/verifier.cc
@@ -34,7 +34,7 @@ const double kDefaultTexelTolerance = 0.002;
void CopyBitsOfMemoryToBuffer(uint8_t* dst,
const uint8_t* src,
uint8_t src_bit_offset,
- uint8_t bits) {
+ uint32_t bits) {
while (src_bit_offset > static_cast<uint8_t>(7)) {
++src;
src_bit_offset = static_cast<uint8_t>(src_bit_offset - kBitsPerByte);
@@ -267,94 +267,60 @@ std::vector<double> GetActualValuesFromTexel(const uint8_t* texel,
for (size_t i = 0; i < fmt->GetSegments().size(); ++i) {
const auto& seg = fmt->GetSegments()[i];
- auto component = seg.GetComponent();
-
if (seg.IsPadding()) {
- bit_offset += component->num_bits;
+ bit_offset += seg.GetNumBits();
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) {
- actual_values[i] =
- 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) {
- double* ptr = reinterpret_cast<double*>(actual);
- actual_values[i] = *ptr;
- } else {
- assert(false && "Bits of component is not for double nor float type");
- }
+ uint32_t num_bits = seg.GetNumBits();
+ CopyBitsOfMemoryToBuffer(actual, texel, bit_offset, num_bits);
+
+ FormatMode mode = seg.GetFormatMode();
+ if (type::Type::IsInt8(mode, num_bits)) {
+ int8_t* ptr8 = nullptr;
+ ptr8 = reinterpret_cast<int8_t*>(actual);
+ actual_values[i] = static_cast<double>(*ptr8);
+ } else if (type::Type::IsInt16(mode, num_bits)) {
+ int16_t* ptr16 = nullptr;
+ ptr16 = reinterpret_cast<int16_t*>(actual);
+ actual_values[i] = static_cast<double>(*ptr16);
+ } else if (type::Type::IsInt32(mode, num_bits)) {
+ int32_t* ptr32 = nullptr;
+ ptr32 = reinterpret_cast<int32_t*>(actual);
+ actual_values[i] = static_cast<double>(*ptr32);
+ } else if (type::Type::IsInt64(mode, num_bits)) {
+ int64_t* ptr64 = nullptr;
+ ptr64 = reinterpret_cast<int64_t*>(actual);
+ actual_values[i] = static_cast<double>(*ptr64);
+ } else if (type::Type::IsUint8(mode, num_bits)) {
+ actual_values[i] = static_cast<double>(*actual);
+ } else if (type::Type::IsUint16(mode, num_bits)) {
+ uint16_t* ptr16 = nullptr;
+ ptr16 = reinterpret_cast<uint16_t*>(actual);
+ actual_values[i] = static_cast<double>(*ptr16);
+ } else if (type::Type::IsUint32(mode, num_bits)) {
+ uint32_t* ptr32 = nullptr;
+ ptr32 = reinterpret_cast<uint32_t*>(actual);
+ actual_values[i] = static_cast<double>(*ptr32);
+ } else if (type::Type::IsUint64(mode, num_bits)) {
+ uint64_t* ptr64 = nullptr;
+ ptr64 = reinterpret_cast<uint64_t*>(actual);
+ actual_values[i] = static_cast<double>(*ptr64);
+ } else if (type::Type::IsFloat32(mode, num_bits)) {
+ float* ptr = reinterpret_cast<float*>(actual);
+ actual_values[i] = static_cast<double>(*ptr);
+ } else if (type::Type::IsFloat64(mode, num_bits)) {
+ double* ptr = reinterpret_cast<double*>(actual);
+ actual_values[i] = *ptr;
+ } else if (type::Type::IsFloat(mode) && num_bits < 32) {
+ actual_values[i] = static_cast<double>(
+ HexFloatToFloat(actual, static_cast<uint8_t>(num_bits)));
} else {
- 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);
- actual_values[i] = static_cast<double>(*ptr8);
- break;
- }
- case 16: {
- int16_t* ptr16 = nullptr;
- ptr16 = reinterpret_cast<int16_t*>(actual);
- actual_values[i] = static_cast<double>(*ptr16);
- break;
- }
- case 32: {
- int32_t* ptr32 = nullptr;
- ptr32 = reinterpret_cast<int32_t*>(actual);
- actual_values[i] = static_cast<double>(*ptr32);
- break;
- }
- case 64: {
- int64_t* ptr64 = nullptr;
- ptr64 = reinterpret_cast<int64_t*>(actual);
- actual_values[i] = static_cast<double>(*ptr64);
- break;
- }
- default: {
- assert(false && "Bits of component is not for integer type");
- }
- }
- } else {
- switch (component->num_bits) {
- case 8: {
- actual_values[i] = static_cast<double>(*actual);
- break;
- }
- case 16: {
- uint16_t* ptr16 = nullptr;
- ptr16 = reinterpret_cast<uint16_t*>(actual);
- actual_values[i] = static_cast<double>(*ptr16);
- break;
- }
- case 32: {
- uint32_t* ptr32 = nullptr;
- ptr32 = reinterpret_cast<uint32_t*>(actual);
- actual_values[i] = static_cast<double>(*ptr32);
- break;
- }
- case 64: {
- uint64_t* ptr64 = nullptr;
- ptr64 = reinterpret_cast<uint64_t*>(actual);
- actual_values[i] = static_cast<double>(*ptr64);
- break;
- }
- default: {
- assert(false && "Bits of component is not for integer type");
- }
- }
- }
+ assert(false && "Incorrect number of bits for number.");
}
- bit_offset += component->num_bits;
+ bit_offset += num_bits;
}
return actual_values;
@@ -366,37 +332,24 @@ std::vector<double> GetActualValuesFromTexel(const uint8_t* texel,
// ::kUFloat, ::kSFloat.
void ScaleTexelValuesIfNeeded(std::vector<double>* texel, const Format* fmt) {
assert(fmt->GetSegments().size() == texel->size());
+
for (size_t i = 0; i < fmt->GetSegments().size(); ++i) {
const auto& seg = fmt->GetSegments()[i];
if (seg.IsPadding())
continue;
- auto component = seg.GetComponent();
-
double scaled_value = (*texel)[i];
- switch (component->mode) {
- case FormatMode::kUNorm:
- 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);
- break;
- case FormatMode::kUInt:
- case FormatMode::kSInt:
- case FormatMode::kUFloat:
- case FormatMode::kSFloat:
- break;
- case FormatMode::kSRGB:
- scaled_value /= static_cast<double>((1 << component->num_bits) - 1);
- if (component->type != FormatComponentType::kA)
- scaled_value = SRGBToLinearValue(scaled_value);
- break;
- case FormatMode::kUScaled:
- case FormatMode::kSScaled:
- assert(false &&
- "FormatMode::kUScaled and ::kSScaled are not implemented");
- break;
+ if (seg.GetFormatMode() == FormatMode::kUNorm) {
+ scaled_value /= static_cast<double>((1 << seg.GetNumBits()) - 1);
+ } else if (seg.GetFormatMode() == FormatMode::kSNorm) {
+ scaled_value /= static_cast<double>((1 << (seg.GetNumBits() - 1)) - 1);
+ } else if (seg.GetFormatMode() == FormatMode::kSRGB) {
+ scaled_value /= static_cast<double>((1 << seg.GetNumBits()) - 1);
+ if (seg.GetName() != FormatComponentType::kA)
+ scaled_value = SRGBToLinearValue(scaled_value);
+ } else if (seg.GetFormatMode() == FormatMode::kSScaled ||
+ seg.GetFormatMode() == FormatMode::kUScaled) {
+ assert(false && "UScaled and SScaled are not implemented");
}
(*texel)[i] = scaled_value;
@@ -418,17 +371,15 @@ bool IsTexelEqualToExpected(const std::vector<double>& texel,
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 (seg.GetName()) {
case FormatComponentType::kA:
- if (!command->IsRGBA()) {
+ if (!command->IsRGBA())
continue;
- }
+
expected = static_cast<double>(command->GetA());
current_tolerance = tolerance[3];
is_current_tolerance_percent = is_tolerance_percent[3];
@@ -469,8 +420,7 @@ std::vector<double> GetTexelInRGBA(const std::vector<double>& texel,
if (seg.IsPadding())
continue;
- auto component = seg.GetComponent();
- switch (component->type) {
+ switch (seg.GetName()) {
case FormatComponentType::kR:
texel_in_rgba[0] = texel[i];
break;
@@ -560,7 +510,7 @@ Result Verifier::Probe(const ProbeCommand* command,
uint32_t count_of_invalid_pixels = 0;
uint32_t first_invalid_i = 0;
uint32_t first_invalid_j = 0;
- std::vector<double> actual_texel_values_on_failure;
+ std::vector<double> failure_values;
for (uint32_t j = 0; j < height; ++j) {
const uint8_t* p = ptr + row_stride * (j + y) + texel_stride * x;
for (uint32_t i = 0; i < width; ++i) {
@@ -570,8 +520,7 @@ Result Verifier::Probe(const ProbeCommand* command,
if (!IsTexelEqualToExpected(actual_texel_values, fmt, command, tolerance,
is_tolerance_percent)) {
if (!count_of_invalid_pixels) {
- actual_texel_values_on_failure =
- GetTexelInRGBA(actual_texel_values, fmt);
+ failure_values = GetTexelInRGBA(actual_texel_values, fmt);
first_invalid_i = i;
first_invalid_j = j;
}
@@ -581,35 +530,34 @@ Result Verifier::Probe(const ProbeCommand* command,
}
if (count_of_invalid_pixels) {
- float scale_factor_for_error_report = fmt->IsNormalized() ? 255.f : 1.f;
-
- return Result(
+ float scale = fmt->IsNormalized() ? 255.f : 1.f;
+ std::string reason =
"Line " + std::to_string(command->GetLine()) +
": Probe failed at: " + std::to_string(x + first_invalid_i) + ", " +
- std::to_string(first_invalid_j + y) + "\n" + " Expected RGBA: " +
- std::to_string(command->GetR() * scale_factor_for_error_report) + ", " +
- std::to_string(command->GetG() * scale_factor_for_error_report) + ", " +
- std::to_string(command->GetB() * scale_factor_for_error_report) +
- (command->IsRGBA() ? ", " +
- std::to_string(command->GetA() *
- scale_factor_for_error_report) +
- "\n Actual RGBA: "
- : "\n Actual RGB: ") +
- std::to_string(static_cast<float>(actual_texel_values_on_failure[0]) *
- scale_factor_for_error_report) +
- ", " +
- std::to_string(static_cast<float>(actual_texel_values_on_failure[1]) *
- scale_factor_for_error_report) +
- ", " +
- std::to_string(static_cast<float>(actual_texel_values_on_failure[2]) *
- scale_factor_for_error_report) +
- (command->IsRGBA()
- ? ", " + std::to_string(static_cast<float>(
- actual_texel_values_on_failure[3]) *
- scale_factor_for_error_report)
- : "") +
- "\n" + "Probe failed in " + std::to_string(count_of_invalid_pixels) +
- " pixels");
+ std::to_string(first_invalid_j + y) + "\n" +
+ " Expected: " + std::to_string(command->GetR() * scale) + ", " +
+ std::to_string(command->GetG() * scale) + ", " +
+ std::to_string(command->GetB() * scale);
+
+ if (command->IsRGBA()) {
+ reason += ", " + std::to_string(command->GetA() * scale);
+ }
+
+ reason +=
+ "\n Actual: " +
+ std::to_string(static_cast<float>(failure_values[0]) * scale) + ", " +
+ std::to_string(static_cast<float>(failure_values[1]) * scale) + ", " +
+ std::to_string(static_cast<float>(failure_values[2]) * scale);
+
+ if (command->IsRGBA()) {
+ reason +=
+ ", " + std::to_string(static_cast<float>(failure_values[3]) * scale);
+ }
+
+ reason += "\nProbe failed in " + std::to_string(count_of_invalid_pixels) +
+ " pixels";
+
+ return Result(reason);
}
return {};
@@ -658,7 +606,7 @@ Result Verifier::ProbeSSBO(const ProbeSSBOCommand* command,
auto segment = segments[k];
// Skip over any padding bytes.
while (segment.IsPadding()) {
- ptr += segment.GetComponent()->SizeInBytes();
+ ptr += segment.PaddingBytes();
++k;
if (k >= segments.size())
k = 0;
@@ -667,25 +615,27 @@ Result Verifier::ProbeSSBO(const ProbeSSBOCommand* command,
}
Result r;
- if (segment.GetComponent()->IsInt8())
+ FormatMode mode = segment.GetFormatMode();
+ uint32_t num_bits = segment.GetNumBits();
+ if (type::Type::IsInt8(mode, num_bits))
r = CheckValue<int8_t>(command, ptr, value);
- else if (segment.GetComponent()->IsUint8())
+ else if (type::Type::IsUint8(mode, num_bits))
r = CheckValue<uint8_t>(command, ptr, value);
- else if (segment.GetComponent()->IsInt16())
+ else if (type::Type::IsInt16(mode, num_bits))
r = CheckValue<int16_t>(command, ptr, value);
- else if (segment.GetComponent()->IsUint16())
+ else if (type::Type::IsUint16(mode, num_bits))
r = CheckValue<uint16_t>(command, ptr, value);
- else if (segment.GetComponent()->IsInt32())
+ else if (type::Type::IsInt32(mode, num_bits))
r = CheckValue<int32_t>(command, ptr, value);
- else if (segment.GetComponent()->IsUint32())
+ else if (type::Type::IsUint32(mode, num_bits))
r = CheckValue<uint32_t>(command, ptr, value);
- else if (segment.GetComponent()->IsInt64())
+ else if (type::Type::IsInt64(mode, num_bits))
r = CheckValue<int64_t>(command, ptr, value);
- else if (segment.GetComponent()->IsUint64())
+ else if (type::Type::IsUint64(mode, num_bits))
r = CheckValue<uint64_t>(command, ptr, value);
- else if (segment.GetComponent()->IsFloat())
+ else if (type::Type::IsFloat32(mode, num_bits))
r = CheckValue<float>(command, ptr, value);
- else if (segment.GetComponent()->IsDouble())
+ else if (type::Type::IsFloat64(mode, num_bits))
r = CheckValue<double>(command, ptr, value);
else
return Result("Unknown datum type");
@@ -696,7 +646,7 @@ Result Verifier::ProbeSSBO(const ProbeSSBOCommand* command,
std::to_string(i));
}
- ptr += segment.GetComponent()->SizeInBytes();
+ ptr += segment.SizeInBytes();
}
return {};
diff --git a/src/verifier_test.cc b/src/verifier_test.cc
index 3cbe86b..42e5aba 100644
--- a/src/verifier_test.cc
+++ b/src/verifier_test.cc
@@ -22,9 +22,9 @@
#include "amber/value.h"
#include "gtest/gtest.h"
#include "src/command.h"
-#include "src/format_parser.h"
#include "src/make_unique.h"
#include "src/pipeline.h"
+#include "src/type_parser.h"
namespace amber {
namespace {
@@ -38,12 +38,15 @@ class VerifierTest : public testing::Test {
if (color_frame_format_)
return color_frame_format_.get();
- FormatParser fp;
- color_frame_format_ = fp.Parse("B8G8R8A8_UNORM");
+ TypeParser parser;
+ color_frame_type_ = parser.Parse("B8G8R8A8_UNORM");
+
+ color_frame_format_ = MakeUnique<Format>(color_frame_type_.get());
return color_frame_format_.get();
}
private:
+ std::unique_ptr<type::Type> color_frame_type_;
std::unique_ptr<Format> color_frame_format_;
};
@@ -142,8 +145,8 @@ TEST_F(VerifierTest, ProbeFrameBufferRelativeSmallExpectFail) {
Result r = verifier.Probe(&probe, GetColorFormat(), 4, 1000, 250, 250,
static_cast<const void*>(frame_buffer));
EXPECT_EQ(
- "Line 1: Probe failed at: 225, 225\n Expected RGBA: 25.500000, "
- "0.000000, 0.000000, 0.000000\n Actual RGBA: 0.000000, 0.000000, "
+ "Line 1: Probe failed at: 225, 225\n Expected: 25.500000, "
+ "0.000000, 0.000000, 0.000000\n Actual: 0.000000, 0.000000, "
"0.000000, 0.000000\nProbe failed in 625 pixels",
r.Error());
}
@@ -195,14 +198,15 @@ TEST_F(VerifierTest, ProbeFrameBufferUInt8) {
uint8_t frame_buffer[4] = {255, 14, 75, 8};
- FormatParser fp;
- auto fmt = fp.Parse("R8G8B8A8_UINT");
+ TypeParser parser;
+ auto type = parser.Parse("R8G8B8A8_UINT");
+ Format fmt(type.get());
Verifier verifier;
- Result r = verifier.Probe(&probe, fmt.get(),
- 4 * static_cast<uint32_t>(sizeof(uint8_t)),
- 4 * static_cast<uint32_t>(sizeof(uint8_t)), 1, 1,
- static_cast<const void*>(&frame_buffer));
+ Result r =
+ verifier.Probe(&probe, &fmt, 4 * static_cast<uint32_t>(sizeof(uint8_t)),
+ 4 * static_cast<uint32_t>(sizeof(uint8_t)), 1, 1,
+ static_cast<const void*>(&frame_buffer));
EXPECT_TRUE(r.IsSuccess());
}
@@ -221,14 +225,15 @@ TEST_F(VerifierTest, ProbeFrameBufferUInt16) {
uint16_t frame_buffer[4] = {65535, 14, 1875, 8};
- FormatParser fp;
- auto fmt = fp.Parse("R16G16B16A16_UINT");
+ TypeParser parser;
+ auto type = parser.Parse("R16G16B16A16_UINT");
+ Format fmt(type.get());
Verifier verifier;
- Result r = verifier.Probe(&probe, fmt.get(),
- 4 * static_cast<uint32_t>(sizeof(uint16_t)),
- 4 * static_cast<uint32_t>(sizeof(uint16_t)), 1, 1,
- static_cast<const void*>(&frame_buffer));
+ Result r =
+ verifier.Probe(&probe, &fmt, 4 * static_cast<uint32_t>(sizeof(uint16_t)),
+ 4 * static_cast<uint32_t>(sizeof(uint16_t)), 1, 1,
+ static_cast<const void*>(&frame_buffer));
EXPECT_TRUE(r.IsSuccess());
}
@@ -247,14 +252,15 @@ TEST_F(VerifierTest, ProbeFrameBufferUInt32) {
uint32_t frame_buffer[4] = {6, 14, 1171875, 8};
- FormatParser fp;
- auto fmt = fp.Parse("R32G32B32A32_UINT");
+ TypeParser parser;
+ auto type = parser.Parse("R32G32B32A32_UINT");
+ Format fmt(type.get());
Verifier verifier;
- Result r = verifier.Probe(&probe, fmt.get(),
- 4 * static_cast<uint32_t>(sizeof(uint32_t)),
- 4 * static_cast<uint32_t>(sizeof(uint32_t)), 1, 1,
- static_cast<const void*>(&frame_buffer));
+ Result r =
+ verifier.Probe(&probe, &fmt, 4 * static_cast<uint32_t>(sizeof(uint32_t)),
+ 4 * static_cast<uint32_t>(sizeof(uint32_t)), 1, 1,
+ static_cast<const void*>(&frame_buffer));
EXPECT_TRUE(r.IsSuccess());
}
@@ -273,14 +279,15 @@ TEST_F(VerifierTest, ProbeFrameBufferUInt64) {
uint64_t frame_buffer[4] = {6, 14, 1171875, 8};
- FormatParser fp;
- auto fmt = fp.Parse("R64G64B64A64_UINT");
+ TypeParser parser;
+ auto type = parser.Parse("R64G64B64A64_UINT");
+ Format fmt(type.get());
Verifier verifier;
- Result r = verifier.Probe(&probe, fmt.get(),
- 4 * static_cast<uint32_t>(sizeof(uint64_t)),
- 4 * static_cast<uint32_t>(sizeof(uint64_t)), 1, 1,
- static_cast<const void*>(&frame_buffer));
+ Result r =
+ verifier.Probe(&probe, &fmt, 4 * static_cast<uint32_t>(sizeof(uint64_t)),
+ 4 * static_cast<uint32_t>(sizeof(uint64_t)), 1, 1,
+ static_cast<const void*>(&frame_buffer));
EXPECT_TRUE(r.IsSuccess());
}
@@ -299,14 +306,15 @@ TEST_F(VerifierTest, ProbeFrameBufferSInt8) {
int8_t frame_buffer[4] = {-6, 14, 75, 8};
- FormatParser fp;
- auto fmt = fp.Parse("R8G8B8A8_SINT");
+ TypeParser parser;
+ auto type = parser.Parse("R8G8B8A8_SINT");
+ Format fmt(type.get());
Verifier verifier;
- Result r = verifier.Probe(&probe, fmt.get(),
- 4 * static_cast<uint32_t>(sizeof(int8_t)),
- 4 * static_cast<uint32_t>(sizeof(int8_t)), 1, 1,
- static_cast<const void*>(&frame_buffer));
+ Result r =
+ verifier.Probe(&probe, &fmt, 4 * static_cast<uint32_t>(sizeof(int8_t)),
+ 4 * static_cast<uint32_t>(sizeof(int8_t)), 1, 1,
+ static_cast<const void*>(&frame_buffer));
EXPECT_TRUE(r.IsSuccess());
}
@@ -325,14 +333,15 @@ TEST_F(VerifierTest, ProbeFrameBufferSInt16) {
int16_t frame_buffer[4] = {-6, 14, 1875, 8};
- FormatParser fp;
- auto fmt = fp.Parse("R16G16B16A16_SINT");
+ TypeParser parser;
+ auto type = parser.Parse("R16G16B16A16_SINT");
+ Format fmt(type.get());
Verifier verifier;
- Result r = verifier.Probe(&probe, fmt.get(),
- 4 * static_cast<uint32_t>(sizeof(int16_t)),
- 4 * static_cast<uint32_t>(sizeof(int16_t)), 1, 1,
- static_cast<const void*>(&frame_buffer));
+ Result r =
+ verifier.Probe(&probe, &fmt, 4 * static_cast<uint32_t>(sizeof(int16_t)),
+ 4 * static_cast<uint32_t>(sizeof(int16_t)), 1, 1,
+ static_cast<const void*>(&frame_buffer));
EXPECT_TRUE(r.IsSuccess());
}
@@ -351,14 +360,15 @@ TEST_F(VerifierTest, ProbeFrameBufferSInt32) {
int32_t frame_buffer[4] = {-6, 14, 1171875, 8};
- FormatParser fp;
- auto fmt = fp.Parse("R32G32B32A32_SINT");
+ TypeParser parser;
+ auto type = parser.Parse("R32G32B32A32_SINT");
+ Format fmt(type.get());
Verifier verifier;
- Result r = verifier.Probe(&probe, fmt.get(),
- 4 * static_cast<uint32_t>(sizeof(int32_t)),
- 4 * static_cast<uint32_t>(sizeof(int32_t)), 1, 1,
- static_cast<const void*>(&frame_buffer));
+ Result r =
+ verifier.Probe(&probe, &fmt, 4 * static_cast<uint32_t>(sizeof(int32_t)),
+ 4 * static_cast<uint32_t>(sizeof(int32_t)), 1, 1,
+ static_cast<const void*>(&frame_buffer));
EXPECT_TRUE(r.IsSuccess());
}
@@ -377,14 +387,15 @@ TEST_F(VerifierTest, ProbeFrameBufferSInt64) {
int64_t frame_buffer[4] = {-6, 14, 1171875, 8};
- FormatParser fp;
- auto fmt = fp.Parse("R64G64B64A64_SINT");
+ TypeParser parser;
+ auto type = parser.Parse("R64G64B64A64_SINT");
+ Format fmt(type.get());
Verifier verifier;
- Result r = verifier.Probe(&probe, fmt.get(),
- 4 * static_cast<uint32_t>(sizeof(int64_t)),
- 4 * static_cast<uint32_t>(sizeof(int64_t)), 1, 1,
- static_cast<const void*>(&frame_buffer));
+ Result r =
+ verifier.Probe(&probe, &fmt, 4 * static_cast<uint32_t>(sizeof(int64_t)),
+ 4 * static_cast<uint32_t>(sizeof(int64_t)), 1, 1,
+ static_cast<const void*>(&frame_buffer));
EXPECT_TRUE(r.IsSuccess());
}
@@ -403,14 +414,15 @@ TEST_F(VerifierTest, ProbeFrameBufferFloat32) {
float frame_buffer[4] = {-6.0f, 14.0f, 0.1171875f, 0.8f};
- FormatParser fp;
- auto fmt = fp.Parse("R32G32B32A32_SFLOAT");
+ TypeParser parser;
+ auto type = parser.Parse("R32G32B32A32_SFLOAT");
+ Format fmt(type.get());
Verifier verifier;
- Result r = verifier.Probe(&probe, fmt.get(),
- 4 * static_cast<uint32_t>(sizeof(float)),
- 4 * static_cast<uint32_t>(sizeof(float)), 1, 1,
- static_cast<const void*>(&frame_buffer));
+ Result r =
+ verifier.Probe(&probe, &fmt, 4 * static_cast<uint32_t>(sizeof(float)),
+ 4 * static_cast<uint32_t>(sizeof(float)), 1, 1,
+ static_cast<const void*>(&frame_buffer));
EXPECT_TRUE(r.IsSuccess());
}
@@ -429,14 +441,15 @@ TEST_F(VerifierTest, ProbeFrameBufferFloat64) {
double frame_buffer[4] = {-6.0, 14.0, 0.1171875, 0.8};
- FormatParser fp;
- auto fmt = fp.Parse("R64G64B64A64_SFLOAT");
+ TypeParser parser;
+ auto type = parser.Parse("R64G64B64A64_SFLOAT");
+ Format fmt(type.get());
Verifier verifier;
- Result r = verifier.Probe(&probe, fmt.get(),
- 4 * static_cast<uint32_t>(sizeof(double)),
- 4 * static_cast<uint32_t>(sizeof(double)), 1, 1,
- static_cast<const void*>(&frame_buffer));
+ Result r =
+ verifier.Probe(&probe, &fmt, 4 * static_cast<uint32_t>(sizeof(double)),
+ 4 * static_cast<uint32_t>(sizeof(double)), 1, 1,
+ static_cast<const void*>(&frame_buffer));
EXPECT_TRUE(r.IsSuccess());
}
@@ -469,11 +482,12 @@ TEST_F(VerifierTest, HexFloatToFloatR16G11B10) {
frame_buffer |= 380ULL << (16ULL + 11ULL);
probe.SetB(0.1171875f);
- Format format;
- format.SetFormatType(FormatType::kUnknown);
- format.AddComponent(FormatComponentType::kR, FormatMode::kSFloat, 16);
- format.AddComponent(FormatComponentType::kG, FormatMode::kUFloat, 11);
- format.AddComponent(FormatComponentType::kB, FormatMode::kUFloat, 10);
+ auto list = MakeUnique<type::List>();
+ list->AddMember(FormatComponentType::kR, FormatMode::kSFloat, 16);
+ list->AddMember(FormatComponentType::kG, FormatMode::kSFloat, 11);
+ list->AddMember(FormatComponentType::kB, FormatMode::kSFloat, 10);
+
+ Format format(list.get());
Verifier verifier;
Result r = verifier.Probe(&probe, &format, 6, 6, 1, 1,
@@ -510,11 +524,12 @@ TEST_F(VerifierTest, HexFloatToFloatR11G16B10) {
frame_buffer |= 380ULL << (16ULL + 11ULL);
probe.SetB(0.1171875f);
- Format format;
- format.SetFormatType(FormatType::kUnknown);
- format.AddComponent(FormatComponentType::kR, FormatMode::kSFloat, 11);
- format.AddComponent(FormatComponentType::kG, FormatMode::kUFloat, 16);
- format.AddComponent(FormatComponentType::kB, FormatMode::kUFloat, 10);
+ auto list = MakeUnique<type::List>();
+ list->AddMember(FormatComponentType::kR, FormatMode::kSFloat, 11);
+ list->AddMember(FormatComponentType::kG, FormatMode::kSFloat, 16);
+ list->AddMember(FormatComponentType::kB, FormatMode::kSFloat, 10);
+
+ Format format(list.get());
Verifier verifier;
Result r = verifier.Probe(&probe, &format, 6, 6, 1, 1,
@@ -551,11 +566,12 @@ TEST_F(VerifierTest, HexFloatToFloatR10G11B16) {
frame_buffer |= 50688ULL << (10ULL + 11ULL);
probe.SetB(-6.0f);
- Format format;
- format.SetFormatType(FormatType::kUnknown);
- format.AddComponent(FormatComponentType::kR, FormatMode::kSFloat, 10);
- format.AddComponent(FormatComponentType::kG, FormatMode::kUFloat, 11);
- format.AddComponent(FormatComponentType::kB, FormatMode::kUFloat, 16);
+ auto list = MakeUnique<type::List>();
+ list->AddMember(FormatComponentType::kR, FormatMode::kSFloat, 10);
+ list->AddMember(FormatComponentType::kG, FormatMode::kSFloat, 11);
+ list->AddMember(FormatComponentType::kB, FormatMode::kSFloat, 16);
+
+ Format format(list.get());
Verifier verifier;
Result r = verifier.Probe(&probe, &format, 6, 6, 1, 1,
@@ -650,9 +666,11 @@ TEST_F(VerifierTest, ProbeSSBOUint8Single) {
ProbeSSBOCommand probe_ssbo(color_buf.get());
- FormatParser fp;
- auto fmt = fp.Parse("R8_UINT");
- probe_ssbo.SetFormat(fmt.get());
+ TypeParser parser;
+ auto type = parser.Parse("R8_UINT");
+ Format fmt(type.get());
+
+ probe_ssbo.SetFormat(&fmt);
probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kEqual);
std::vector<Value> values;
@@ -674,10 +692,11 @@ TEST_F(VerifierTest, ProbeSSBOUint8Multiple) {
ProbeSSBOCommand probe_ssbo(color_buf.get());
- FormatParser fp;
- auto fmt = fp.Parse("R8_UINT");
+ TypeParser parser;
+ auto type = parser.Parse("R8_UINT");
+ Format fmt(type.get());
- probe_ssbo.SetFormat(fmt.get());
+ probe_ssbo.SetFormat(&fmt);
probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kEqual);
std::vector<Value> values;
@@ -700,10 +719,11 @@ TEST_F(VerifierTest, ProbeSSBOUint8Many) {
ProbeSSBOCommand probe_ssbo(color_buf.get());
- FormatParser fp;
- auto fmt = fp.Parse("R8_UINT");
+ TypeParser parser;
+ auto type = parser.Parse("R8_UINT");
+ Format fmt(type.get());
- probe_ssbo.SetFormat(fmt.get());
+ probe_ssbo.SetFormat(&fmt);
probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kEqual);
std::vector<Value> values;
@@ -730,9 +750,11 @@ TEST_F(VerifierTest, ProbeSSBOUint32Single) {
ProbeSSBOCommand probe_ssbo(color_buf.get());
- FormatParser fp;
- auto fmt = fp.Parse("R32_UINT");
- probe_ssbo.SetFormat(fmt.get());
+ TypeParser parser;
+ auto type = parser.Parse("R32_UINT");
+ Format fmt(type.get());
+
+ probe_ssbo.SetFormat(&fmt);
probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kEqual);
std::vector<Value> values;
@@ -754,9 +776,11 @@ TEST_F(VerifierTest, ProbeSSBOUint32Multiple) {
ProbeSSBOCommand probe_ssbo(color_buf.get());
- FormatParser fp;
- auto fmt = fp.Parse("R32_UINT");
- probe_ssbo.SetFormat(fmt.get());
+ TypeParser parser;
+ auto type = parser.Parse("R32_UINT");
+ Format fmt(type.get());
+
+ probe_ssbo.SetFormat(&fmt);
probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kEqual);
std::vector<Value> values;
@@ -780,9 +804,11 @@ TEST_F(VerifierTest, ProbeSSBOUint32Many) {
ProbeSSBOCommand probe_ssbo(color_buf.get());
- FormatParser fp;
- auto fmt = fp.Parse("R32_UINT");
- probe_ssbo.SetFormat(fmt.get());
+ TypeParser parser;
+ auto type = parser.Parse("R32_UINT");
+ Format fmt(type.get());
+
+ probe_ssbo.SetFormat(&fmt);
probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kEqual);
std::vector<Value> values;
@@ -809,9 +835,11 @@ TEST_F(VerifierTest, ProbeSSBOFloatSingle) {
ProbeSSBOCommand probe_ssbo(color_buf.get());
- FormatParser fp;
- auto fmt = fp.Parse("R32_SFLOAT");
- probe_ssbo.SetFormat(fmt.get());
+ TypeParser parser;
+ auto type = parser.Parse("R32_SFLOAT");
+ Format fmt(type.get());
+
+ probe_ssbo.SetFormat(&fmt);
probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kEqual);
std::vector<Value> values;
@@ -833,9 +861,11 @@ TEST_F(VerifierTest, ProbeSSBOFloatMultiple) {
ProbeSSBOCommand probe_ssbo(color_buf.get());
- FormatParser fp;
- auto fmt = fp.Parse("R32_SFLOAT");
- probe_ssbo.SetFormat(fmt.get());
+ TypeParser parser;
+ auto type = parser.Parse("R32_SFLOAT");
+ Format fmt(type.get());
+
+ probe_ssbo.SetFormat(&fmt);
probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kEqual);
std::vector<Value> values;
@@ -859,9 +889,11 @@ TEST_F(VerifierTest, ProbeSSBOFloatMany) {
ProbeSSBOCommand probe_ssbo(color_buf.get());
- FormatParser fp;
- auto fmt = fp.Parse("R32_SFLOAT");
- probe_ssbo.SetFormat(fmt.get());
+ TypeParser parser;
+ auto type = parser.Parse("R32_SFLOAT");
+ Format fmt(type.get());
+
+ probe_ssbo.SetFormat(&fmt);
probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kEqual);
std::vector<Value> values;
@@ -888,9 +920,11 @@ TEST_F(VerifierTest, ProbeSSBODoubleSingle) {
ProbeSSBOCommand probe_ssbo(color_buf.get());
- FormatParser fp;
- auto fmt = fp.Parse("R64_SFLOAT");
- probe_ssbo.SetFormat(fmt.get());
+ TypeParser parser;
+ auto type = parser.Parse("R64_SFLOAT");
+ Format fmt(type.get());
+
+ probe_ssbo.SetFormat(&fmt);
probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kEqual);
std::vector<Value> values;
@@ -912,9 +946,11 @@ TEST_F(VerifierTest, ProbeSSBODoubleMultiple) {
ProbeSSBOCommand probe_ssbo(color_buf.get());
- FormatParser fp;
- auto fmt = fp.Parse("R64_SFLOAT");
- probe_ssbo.SetFormat(fmt.get());
+ TypeParser parser;
+ auto type = parser.Parse("R64_SFLOAT");
+ Format fmt(type.get());
+
+ probe_ssbo.SetFormat(&fmt);
probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kEqual);
std::vector<Value> values;
@@ -938,9 +974,11 @@ TEST_F(VerifierTest, ProbeSSBODoubleMany) {
ProbeSSBOCommand probe_ssbo(color_buf.get());
- FormatParser fp;
- auto fmt = fp.Parse("R64_SFLOAT");
- probe_ssbo.SetFormat(fmt.get());
+ TypeParser parser;
+ auto type = parser.Parse("R64_SFLOAT");
+ Format fmt(type.get());
+
+ probe_ssbo.SetFormat(&fmt);
probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kEqual);
std::vector<Value> values;
@@ -967,9 +1005,11 @@ TEST_F(VerifierTest, ProbeSSBOEqualFail) {
ProbeSSBOCommand probe_ssbo(color_buf.get());
- FormatParser fp;
- auto fmt = fp.Parse("R64_SFLOAT");
- probe_ssbo.SetFormat(fmt.get());
+ TypeParser parser;
+ auto type = parser.Parse("R64_SFLOAT");
+ Format fmt(type.get());
+
+ probe_ssbo.SetFormat(&fmt);
probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kEqual);
std::vector<Value> values;
@@ -995,9 +1035,11 @@ TEST_F(VerifierTest, ProbeSSBOFuzzyEqualWithAbsoluteTolerance) {
ProbeSSBOCommand probe_ssbo(color_buf.get());
- FormatParser fp;
- auto fmt = fp.Parse("R64_SFLOAT");
- probe_ssbo.SetFormat(fmt.get());
+ TypeParser parser;
+ auto type = parser.Parse("R64_SFLOAT");
+ Format fmt(type.get());
+
+ probe_ssbo.SetFormat(&fmt);
probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kFuzzyEqual);
std::vector<Probe::Tolerance> tolerances;
@@ -1030,9 +1072,11 @@ TEST_F(VerifierTest, ProbeSSBOFuzzyEqualWithAbsoluteToleranceFail) {
ProbeSSBOCommand probe_ssbo(color_buf.get());
- FormatParser fp;
- auto fmt = fp.Parse("R64_SFLOAT");
- probe_ssbo.SetFormat(fmt.get());
+ TypeParser parser;
+ auto type = parser.Parse("R64_SFLOAT");
+ Format fmt(type.get());
+
+ probe_ssbo.SetFormat(&fmt);
probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kFuzzyEqual);
std::vector<Probe::Tolerance> tolerances;
@@ -1062,9 +1106,11 @@ TEST_F(VerifierTest, ProbeSSBOFuzzyEqualWithRelativeTolerance) {
ProbeSSBOCommand probe_ssbo(color_buf.get());
- FormatParser fp;
- auto fmt = fp.Parse("R64_SFLOAT");
- probe_ssbo.SetFormat(fmt.get());
+ TypeParser parser;
+ auto type = parser.Parse("R64_SFLOAT");
+ Format fmt(type.get());
+
+ probe_ssbo.SetFormat(&fmt);
probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kFuzzyEqual);
std::vector<Probe::Tolerance> tolerances;
@@ -1097,9 +1143,11 @@ TEST_F(VerifierTest, ProbeSSBOFuzzyEqualWithRelativeToleranceFail) {
ProbeSSBOCommand probe_ssbo(color_buf.get());
- FormatParser fp;
- auto fmt = fp.Parse("R64_SFLOAT");
- probe_ssbo.SetFormat(fmt.get());
+ TypeParser parser;
+ auto type = parser.Parse("R64_SFLOAT");
+ Format fmt(type.get());
+
+ probe_ssbo.SetFormat(&fmt);
probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kFuzzyEqual);
std::vector<Probe::Tolerance> tolerances;
@@ -1129,9 +1177,11 @@ TEST_F(VerifierTest, ProbeSSBONotEqual) {
ProbeSSBOCommand probe_ssbo(color_buf.get());
- FormatParser fp;
- auto fmt = fp.Parse("R64_SFLOAT");
- probe_ssbo.SetFormat(fmt.get());
+ TypeParser parser;
+ auto type = parser.Parse("R64_SFLOAT");
+ Format fmt(type.get());
+
+ probe_ssbo.SetFormat(&fmt);
probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kNotEqual);
std::vector<Value> values;
@@ -1155,9 +1205,11 @@ TEST_F(VerifierTest, ProbeSSBONotEqualFail) {
ProbeSSBOCommand probe_ssbo(color_buf.get());
- FormatParser fp;
- auto fmt = fp.Parse("R64_SFLOAT");
- probe_ssbo.SetFormat(fmt.get());
+ TypeParser parser;
+ auto type = parser.Parse("R64_SFLOAT");
+ Format fmt(type.get());
+
+ probe_ssbo.SetFormat(&fmt);
probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kNotEqual);
std::vector<Value> values;
@@ -1183,9 +1235,11 @@ TEST_F(VerifierTest, ProbeSSBOLess) {
ProbeSSBOCommand probe_ssbo(color_buf.get());
- FormatParser fp;
- auto fmt = fp.Parse("R64_SFLOAT");
- probe_ssbo.SetFormat(fmt.get());
+ TypeParser parser;
+ auto type = parser.Parse("R64_SFLOAT");
+ Format fmt(type.get());
+
+ probe_ssbo.SetFormat(&fmt);
probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kLess);
std::vector<Value> values;
@@ -1209,9 +1263,11 @@ TEST_F(VerifierTest, ProbeSSBOLessFail) {
ProbeSSBOCommand probe_ssbo(color_buf.get());
- FormatParser fp;
- auto fmt = fp.Parse("R64_SFLOAT");
- probe_ssbo.SetFormat(fmt.get());
+ TypeParser parser;
+ auto type = parser.Parse("R64_SFLOAT");
+ Format fmt(type.get());
+
+ probe_ssbo.SetFormat(&fmt);
probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kLess);
std::vector<Value> values;
@@ -1237,9 +1293,11 @@ TEST_F(VerifierTest, ProbeSSBOLessOrEqual) {
ProbeSSBOCommand probe_ssbo(color_buf.get());
- FormatParser fp;
- auto fmt = fp.Parse("R64_SFLOAT");
- probe_ssbo.SetFormat(fmt.get());
+ TypeParser parser;
+ auto type = parser.Parse("R64_SFLOAT");
+ Format fmt(type.get());
+
+ probe_ssbo.SetFormat(&fmt);
probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kLessOrEqual);
std::vector<Value> values;
@@ -1263,9 +1321,11 @@ TEST_F(VerifierTest, ProbeSSBOLessOrEqualFail) {
ProbeSSBOCommand probe_ssbo(color_buf.get());
- FormatParser fp;
- auto fmt = fp.Parse("R64_SFLOAT");
- probe_ssbo.SetFormat(fmt.get());
+ TypeParser parser;
+ auto type = parser.Parse("R64_SFLOAT");
+ Format fmt(type.get());
+
+ probe_ssbo.SetFormat(&fmt);
probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kLessOrEqual);
std::vector<Value> values;
@@ -1291,9 +1351,11 @@ TEST_F(VerifierTest, ProbeSSBOGreater) {
ProbeSSBOCommand probe_ssbo(color_buf.get());
- FormatParser fp;
- auto fmt = fp.Parse("R64_SFLOAT");
- probe_ssbo.SetFormat(fmt.get());
+ TypeParser parser;
+ auto type = parser.Parse("R64_SFLOAT");
+ Format fmt(type.get());
+
+ probe_ssbo.SetFormat(&fmt);
probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kGreater);
std::vector<Value> values;
@@ -1317,9 +1379,11 @@ TEST_F(VerifierTest, ProbeSSBOGreaterFail) {
ProbeSSBOCommand probe_ssbo(color_buf.get());
- FormatParser fp;
- auto fmt = fp.Parse("R64_SFLOAT");
- probe_ssbo.SetFormat(fmt.get());
+ TypeParser parser;
+ auto type = parser.Parse("R64_SFLOAT");
+ Format fmt(type.get());
+
+ probe_ssbo.SetFormat(&fmt);
probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kGreater);
std::vector<Value> values;
@@ -1345,9 +1409,11 @@ TEST_F(VerifierTest, ProbeSSBOGreaterOrEqual) {
ProbeSSBOCommand probe_ssbo(color_buf.get());
- FormatParser fp;
- auto fmt = fp.Parse("R64_SFLOAT");
- probe_ssbo.SetFormat(fmt.get());
+ TypeParser parser;
+ auto type = parser.Parse("R64_SFLOAT");
+ Format fmt(type.get());
+
+ probe_ssbo.SetFormat(&fmt);
probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kGreaterOrEqual);
std::vector<Value> values;
@@ -1371,9 +1437,11 @@ TEST_F(VerifierTest, ProbeSSBOGreaterOrEqualFail) {
ProbeSSBOCommand probe_ssbo(color_buf.get());
- FormatParser fp;
- auto fmt = fp.Parse("R64_SFLOAT");
- probe_ssbo.SetFormat(fmt.get());
+ TypeParser parser;
+ auto type = parser.Parse("R64_SFLOAT");
+ Format fmt(type.get());
+
+ probe_ssbo.SetFormat(&fmt);
probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kGreaterOrEqual);
std::vector<Value> values;
@@ -1415,8 +1483,8 @@ TEST_F(VerifierTest, CheckRGBAOrderForFailure) {
static_cast<const void*>(&frame_buffer));
EXPECT_FALSE(r.IsSuccess());
EXPECT_EQ(
- "Line 1: Probe failed at: 0, 0\n Expected RGBA: 153.000000, 102.000000, "
- "0.000000, 76.500000\n Actual RGBA: 75.000000, 14.000000, 255.000000, "
+ "Line 1: Probe failed at: 0, 0\n Expected: 153.000000, 102.000000, "
+ "0.000000, 76.500000\n Actual: 75.000000, 14.000000, 255.000000, "
"8.000000\nProbe failed in 1 pixels",
r.Error());
}
@@ -1427,9 +1495,11 @@ TEST_F(VerifierTest, ProbeSSBOWithPadding) {
ProbeSSBOCommand probe_ssbo(color_buf.get());
- FormatParser fp;
- auto fmt = fp.Parse("float/vec2");
- probe_ssbo.SetFormat(fmt.get());
+ TypeParser parser;
+ auto type = parser.Parse("float/vec2");
+ Format fmt(type.get());
+
+ probe_ssbo.SetFormat(&fmt);
ASSERT_TRUE(probe_ssbo.GetFormat() != nullptr);
probe_ssbo.SetComparator(ProbeSSBOCommand::Comparator::kLessOrEqual);
diff --git a/src/vkscript/command_parser.cc b/src/vkscript/command_parser.cc
index 5123991..dd4f918 100644
--- a/src/vkscript/command_parser.cc
+++ b/src/vkscript/command_parser.cc
@@ -22,9 +22,9 @@
#include <utility>
#include "src/command_data.h"
-#include "src/format_parser.h"
#include "src/make_unique.h"
#include "src/tokenizer.h"
+#include "src/type_parser.h"
#include "src/vkscript/datum_type_parser.h"
namespace amber {
@@ -491,7 +491,7 @@ Result CommandParser::ParseValues(const std::string& name,
while (!token->IsEOL() && !token->IsEOS()) {
Value v;
- if ((fmt->IsFloat() || fmt->IsDouble())) {
+ if ((fmt->IsFloat32() || fmt->IsFloat64())) {
if (!token->IsInteger() && !token->IsDouble()) {
return Result(std::string("Invalid value provided to ") + name +
" command: " + token->ToOriginalString());
@@ -520,7 +520,7 @@ Result CommandParser::ParseValues(const std::string& name,
// This could overflow, but I don't really expect us to get command files
// that big ....
- size_t num_per_row = fmt->RowCount();
+ size_t num_per_row = fmt->GetType()->RowCount();
if (seen == 0 || (seen % num_per_row) != 0) {
return Result(std::string("Incorrect number of values provided to ") +
name + " command");
@@ -589,14 +589,16 @@ Result CommandParser::ProcessSSBO() {
token->ToOriginalString());
DatumTypeParser tp;
- auto fmt = tp.Parse(token->AsString());
- if (!fmt)
+ auto type = tp.Parse(token->AsString());
+ if (!type)
return Result("Invalid type provided: " + token->AsString());
+ auto fmt = MakeUnique<Format>(type.get());
auto* buf = cmd->GetBuffer();
if (buf->FormatIsDefault() || !buf->GetFormat()) {
buf->SetFormat(fmt.get());
script_->RegisterFormat(std::move(fmt));
+ script_->RegisterType(std::move(type));
} else if (!buf->GetFormat()->Equal(fmt.get())) {
return Result("probe ssbo format does not match buffer format");
}
@@ -641,10 +643,13 @@ Result CommandParser::ProcessSSBO() {
// Set a default format into the buffer if needed.
if (!buf->GetFormat()) {
- FormatParser fp;
- auto fmt = fp.Parse("R8_SINT");
+ TypeParser parser;
+ auto type = parser.Parse("R8_SINT");
+ auto fmt = MakeUnique<Format>(type.get());
buf->SetFormat(fmt.get());
script_->RegisterFormat(std::move(fmt));
+ script_->RegisterType(std::move(type));
+
// This has to come after the SetFormat() call because SetFormat() resets
// the value back to false.
buf->SetFormatIsDefault(true);
@@ -740,10 +745,12 @@ Result CommandParser::ProcessUniform() {
}
DatumTypeParser tp;
- auto fmt = tp.Parse(token->AsString());
- if (!fmt)
+ auto type = tp.Parse(token->AsString());
+ if (!type)
return Result("Invalid type provided: " + token->AsString());
+ auto fmt = MakeUnique<Format>(type.get());
+
// uniform is always std140.
if (is_ubo)
fmt->SetLayout(Format::Layout::kStd140);
@@ -752,6 +759,7 @@ Result CommandParser::ProcessUniform() {
if (buf->FormatIsDefault() || !buf->GetFormat()) {
buf->SetFormat(fmt.get());
script_->RegisterFormat(std::move(fmt));
+ script_->RegisterType(std::move(type));
} else if (!buf->GetFormat()->Equal(fmt.get())) {
return Result("probe ssbo format does not match buffer format");
}
@@ -2018,8 +2026,8 @@ Result CommandParser::ProcessProbeSSBO() {
token->ToOriginalString());
DatumTypeParser tp;
- auto fmt = tp.Parse(token->AsString());
- if (!fmt)
+ auto type = tp.Parse(token->AsString());
+ if (!type)
return Result("Invalid type provided: " + token->AsString());
token = tokenizer_->NextToken();
@@ -2061,6 +2069,7 @@ Result CommandParser::ProcessProbeSSBO() {
std::to_string(binding));
}
+ auto fmt = MakeUnique<Format>(type.get());
if (buffer->FormatIsDefault() || !buffer->GetFormat()) {
buffer->SetFormat(fmt.get());
} else if (buffer->GetFormat() && !buffer->GetFormat()->Equal(fmt.get())) {
@@ -2075,6 +2084,7 @@ Result CommandParser::ProcessProbeSSBO() {
cmd->SetBinding(binding);
script_->RegisterFormat(std::move(fmt));
+ script_->RegisterType(std::move(type));
if (!token->IsInteger())
return Result("Invalid offset for probe ssbo command: " +
diff --git a/src/vkscript/command_parser_test.cc b/src/vkscript/command_parser_test.cc
index 1efba07..f88006c 100644
--- a/src/vkscript/command_parser_test.cc
+++ b/src/vkscript/command_parser_test.cc
@@ -3074,6 +3074,7 @@ TEST_F(CommandParserTest, SSBOSubdataWithFloat) {
Pipeline pipeline(PipelineType::kGraphics);
Script script;
+
CommandParser cp(&script, &pipeline, 1, data);
Result r = cp.Parse();
ASSERT_TRUE(r.IsSuccess()) << r.Error();
@@ -3090,9 +3091,12 @@ TEST_F(CommandParserTest, SSBOSubdataWithFloat) {
ASSERT_TRUE(cmd->IsSubdata());
auto* fmt = cmd->GetBuffer()->GetFormat();
- EXPECT_TRUE(fmt->IsFloat());
- EXPECT_EQ(1U, fmt->ColumnCount());
- EXPECT_EQ(3U, fmt->RowCount());
+ ASSERT_TRUE(fmt->GetType()->IsNumber());
+
+ auto n = fmt->GetType()->AsNumber();
+ EXPECT_TRUE(type::Type::IsFloat32(n->GetFormatMode(), n->NumBits()));
+ EXPECT_EQ(1U, fmt->GetType()->ColumnCount());
+ EXPECT_EQ(3U, fmt->GetType()->RowCount());
const auto& values = cmd->GetValues();
std::vector<float> results = {2.3f, 4.2f, 1.2f};
@@ -3134,9 +3138,12 @@ TEST_F(CommandParserTest, SSBOSubdataWithDescriptorSet) {
EXPECT_EQ(16U, cmd->GetOffset());
auto* fmt = cmd->GetBuffer()->GetFormat();
- EXPECT_TRUE(fmt->IsFloat());
- EXPECT_EQ(1U, fmt->ColumnCount());
- EXPECT_EQ(3U, fmt->RowCount());
+ ASSERT_TRUE(fmt->GetType()->IsNumber());
+
+ auto n = fmt->GetType()->AsNumber();
+ EXPECT_TRUE(type::Type::IsFloat32(n->GetFormatMode(), n->NumBits()));
+ EXPECT_EQ(1U, fmt->GetType()->ColumnCount());
+ EXPECT_EQ(3U, fmt->GetType()->RowCount());
const auto& values = cmd->GetValues();
std::vector<float> results = {2.3f, 4.2f, 1.2f};
@@ -3167,9 +3174,12 @@ TEST_F(CommandParserTest, SSBOSubdataWithInts) {
EXPECT_EQ(8U, cmd->GetOffset());
auto* fmt = cmd->GetBuffer()->GetFormat();
- EXPECT_TRUE(fmt->IsInt16());
- EXPECT_EQ(1U, fmt->ColumnCount());
- EXPECT_EQ(3U, fmt->RowCount());
+ ASSERT_TRUE(fmt->GetType()->IsNumber());
+
+ auto n = fmt->GetType()->AsNumber();
+ EXPECT_TRUE(type::Type::IsInt16(n->GetFormatMode(), n->NumBits()));
+ EXPECT_EQ(1U, fmt->GetType()->ColumnCount());
+ EXPECT_EQ(3U, fmt->GetType()->RowCount());
const auto& values = cmd->GetValues();
std::vector<int16_t> results = {2, 4, 1};
@@ -3200,9 +3210,12 @@ TEST_F(CommandParserTest, SSBOSubdataWithMultipleVectors) {
EXPECT_EQ(8U, cmd->GetOffset());
auto* fmt = cmd->GetBuffer()->GetFormat();
- EXPECT_TRUE(fmt->IsInt16());
- EXPECT_EQ(1U, fmt->ColumnCount());
- EXPECT_EQ(3U, fmt->RowCount());
+ ASSERT_TRUE(fmt->GetType()->IsNumber());
+
+ auto n = fmt->GetType()->AsNumber();
+ EXPECT_TRUE(type::Type::IsInt16(n->GetFormatMode(), n->NumBits()));
+ EXPECT_EQ(1U, fmt->GetType()->ColumnCount());
+ EXPECT_EQ(3U, fmt->GetType()->RowCount());
const auto& values = cmd->GetValues();
std::vector<int16_t> results = {2, 4, 1, 3, 6, 8};
@@ -3332,14 +3345,16 @@ TEST_F(CommandParserTest, Uniform) {
EXPECT_EQ(32U, cmd->GetOffset());
auto* fmt = cmd->GetBuffer()->GetFormat();
- EXPECT_TRUE(fmt->IsFloat());
- EXPECT_EQ(1U, fmt->ColumnCount());
- EXPECT_EQ(3U, fmt->RowCount());
+ ASSERT_TRUE(fmt->GetType()->IsNumber());
+
+ auto n = fmt->GetType()->AsNumber();
+ EXPECT_TRUE(type::Type::IsFloat32(n->GetFormatMode(), n->NumBits()));
+ EXPECT_EQ(1U, fmt->GetType()->ColumnCount());
+ EXPECT_EQ(3U, fmt->GetType()->RowCount());
const auto* buf = cmd->GetBuffer();
const auto* values = buf->GetValues<float>();
std::vector<float> results = {2.1f, 3.2f, 4.3f, 0.f};
- ASSERT_EQ(results.size(), buf->ValueCount());
for (size_t i = 0; i < results.size(); ++i) {
EXPECT_FLOAT_EQ(results[i], values[i]);
}
@@ -3374,14 +3389,16 @@ TEST_F(CommandParserTest, UniformWithContinuation) {
EXPECT_EQ(16U, cmd->GetOffset());
auto* fmt = cmd->GetBuffer()->GetFormat();
- EXPECT_TRUE(fmt->IsFloat());
- EXPECT_EQ(1U, fmt->ColumnCount());
- EXPECT_EQ(3U, fmt->RowCount());
+ ASSERT_TRUE(fmt->GetType()->IsNumber());
+
+ auto n = fmt->GetType()->AsNumber();
+ EXPECT_TRUE(type::Type::IsFloat32(n->GetFormatMode(), n->NumBits()));
+ EXPECT_EQ(1U, fmt->GetType()->ColumnCount());
+ EXPECT_EQ(3U, fmt->GetType()->RowCount());
const auto* buf = cmd->GetBuffer();
const auto* values = buf->GetValues<float>();
std::vector<float> results = {2.1f, 3.2f, 4.3f, 0.f, 5.4f, 6.7f, 8.9f, 0.f};
- ASSERT_EQ(results.size(), buf->ValueCount());
for (size_t i = 0; i < results.size(); ++i) {
EXPECT_FLOAT_EQ(results[i], values[i]);
}
@@ -3452,9 +3469,12 @@ TEST_F(CommandParserTest, UniformUBO) {
EXPECT_EQ(static_cast<uint32_t>(0), cmd->GetOffset());
auto* fmt = cmd->GetBuffer()->GetFormat();
- EXPECT_TRUE(fmt->IsFloat());
- EXPECT_EQ(1U, fmt->ColumnCount());
- EXPECT_EQ(3U, fmt->RowCount());
+ ASSERT_TRUE(fmt->GetType()->IsNumber());
+
+ auto n = fmt->GetType()->AsNumber();
+ EXPECT_TRUE(type::Type::IsFloat32(n->GetFormatMode(), n->NumBits()));
+ EXPECT_EQ(1U, fmt->GetType()->ColumnCount());
+ EXPECT_EQ(3U, fmt->GetType()->RowCount());
const auto& values = cmd->GetValues();
std::vector<float> results = {2.1f, 3.2f, 4.3f};
@@ -3507,9 +3527,12 @@ TEST_F(CommandParserTest, UniformUBOWithDescriptorSet) {
EXPECT_EQ(16U, cmd->GetOffset());
auto* fmt = cmd->GetBuffer()->GetFormat();
- EXPECT_TRUE(fmt->IsFloat());
- EXPECT_EQ(1U, fmt->ColumnCount());
- EXPECT_EQ(3U, fmt->RowCount());
+ ASSERT_TRUE(fmt->GetType()->IsNumber());
+
+ auto n = fmt->GetType()->AsNumber();
+ EXPECT_TRUE(type::Type::IsFloat32(n->GetFormatMode(), n->NumBits()));
+ EXPECT_EQ(1U, fmt->GetType()->ColumnCount());
+ EXPECT_EQ(3U, fmt->GetType()->RowCount());
const auto& values = cmd->GetValues();
std::vector<float> results = {2.1f, 3.2f, 4.3f};
@@ -3925,9 +3948,12 @@ probe ssbo vec3 3:6 2 >= 2.3 4.2 1.2)";
cmd->GetComparator());
auto* fmt = cmd->GetFormat();
- EXPECT_TRUE(fmt->IsFloat());
- EXPECT_EQ(1U, fmt->ColumnCount());
- EXPECT_EQ(3U, fmt->RowCount());
+ ASSERT_TRUE(fmt->GetType()->IsNumber());
+
+ auto n = fmt->GetType()->AsNumber();
+ EXPECT_TRUE(type::Type::IsFloat32(n->GetFormatMode(), n->NumBits()));
+ EXPECT_EQ(1U, fmt->GetType()->ColumnCount());
+ EXPECT_EQ(3U, fmt->GetType()->RowCount());
const auto& values = cmd->GetValues();
std::vector<float> results = {2.3f, 4.2f, 1.2f};
@@ -3960,9 +3986,12 @@ probe ssbo vec3 6 2 >= 2.3 4.2 1.2)";
cmd->GetComparator());
auto* fmt = cmd->GetFormat();
- EXPECT_TRUE(fmt->IsFloat());
- EXPECT_EQ(1U, fmt->ColumnCount());
- EXPECT_EQ(3U, fmt->RowCount());
+ ASSERT_TRUE(fmt->GetType()->IsNumber());
+
+ auto n = fmt->GetType()->AsNumber();
+ EXPECT_TRUE(type::Type::IsFloat32(n->GetFormatMode(), n->NumBits()));
+ EXPECT_EQ(1U, fmt->GetType()->ColumnCount());
+ EXPECT_EQ(3U, fmt->GetType()->RowCount());
const auto& values = cmd->GetValues();
std::vector<float> results = {2.3f, 4.2f, 1.2f};
@@ -3995,9 +4024,12 @@ probe ssbo vec3 6 2 >= 2.3 4.2 1.2)";
cmd->GetComparator());
auto* fmt = cmd->GetFormat();
- EXPECT_TRUE(fmt->IsFloat());
- EXPECT_EQ(1U, fmt->ColumnCount());
- EXPECT_EQ(3U, fmt->RowCount());
+ ASSERT_TRUE(fmt->GetType()->IsNumber());
+
+ auto n = fmt->GetType()->AsNumber();
+ EXPECT_TRUE(type::Type::IsFloat32(n->GetFormatMode(), n->NumBits()));
+ EXPECT_EQ(1U, fmt->GetType()->ColumnCount());
+ EXPECT_EQ(3U, fmt->GetType()->RowCount());
const auto& values = cmd->GetValues();
std::vector<float> results = {2.3f, 4.2f, 1.2f};
@@ -4029,9 +4061,12 @@ probe ssbo i16vec3 6 2 <= 2 4 1)";
EXPECT_EQ(ProbeSSBOCommand::Comparator::kLessOrEqual, cmd->GetComparator());
auto* fmt = cmd->GetFormat();
- EXPECT_TRUE(fmt->IsInt16());
- EXPECT_EQ(1U, fmt->ColumnCount());
- EXPECT_EQ(3U, fmt->RowCount());
+ ASSERT_TRUE(fmt->GetType()->IsNumber());
+
+ auto n = fmt->GetType()->AsNumber();
+ EXPECT_TRUE(type::Type::IsInt16(n->GetFormatMode(), n->NumBits()));
+ EXPECT_EQ(1U, fmt->GetType()->ColumnCount());
+ EXPECT_EQ(3U, fmt->GetType()->RowCount());
const auto& values = cmd->GetValues();
std::vector<int16_t> results = {2, 4, 1};
@@ -4063,9 +4098,12 @@ probe ssbo i16vec3 6 2 == 2 4 1 3 6 8)";
EXPECT_EQ(ProbeSSBOCommand::Comparator::kEqual, cmd->GetComparator());
auto* fmt = cmd->GetFormat();
- EXPECT_TRUE(fmt->IsInt16());
- EXPECT_EQ(1U, fmt->ColumnCount());
- EXPECT_EQ(3U, fmt->RowCount());
+ ASSERT_TRUE(fmt->GetType()->IsNumber());
+
+ auto n = fmt->GetType()->AsNumber();
+ EXPECT_TRUE(type::Type::IsInt16(n->GetFormatMode(), n->NumBits()));
+ EXPECT_EQ(1U, fmt->GetType()->ColumnCount());
+ EXPECT_EQ(3U, fmt->GetType()->RowCount());
const auto& values = cmd->GetValues();
std::vector<int16_t> results = {2, 4, 1, 3, 6, 8};
diff --git a/src/vkscript/datum_type_parser.cc b/src/vkscript/datum_type_parser.cc
index 2a9dcaf..9062960 100644
--- a/src/vkscript/datum_type_parser.cc
+++ b/src/vkscript/datum_type_parser.cc
@@ -14,114 +14,90 @@
#include "src/vkscript/datum_type_parser.h"
-#include "src/format_parser.h"
#include "src/make_unique.h"
+#include "src/type_parser.h"
namespace amber {
namespace vkscript {
-namespace {
-
-FormatComponentType FORMAT_TYPES[] = {
- FormatComponentType::kR, FormatComponentType::kG, FormatComponentType::kB,
- FormatComponentType::kA};
-
-} // namespace
DatumTypeParser::DatumTypeParser() = default;
DatumTypeParser::~DatumTypeParser() = default;
-std::unique_ptr<Format> DatumTypeParser::Parse(const std::string& data) {
- std::unique_ptr<Format> fmt;
-
- FormatParser fp;
- bool matrix = false;
- if (data == "int") {
- fmt = fp.Parse("R32_SINT");
- } else if (data == "uint") {
- fmt = fp.Parse("R32_UINT");
- } else if (data == "int8_t") {
- fmt = fp.Parse("R8_SINT");
- } else if (data == "uint8_t") {
- fmt = fp.Parse("R8_UINT");
- } else if (data == "int16_t") {
- fmt = fp.Parse("R16_SINT");
- } else if (data == "uint16_t") {
- fmt = fp.Parse("R16_UINT");
- } else if (data == "int64_t") {
- fmt = fp.Parse("R64_SINT");
- } else if (data == "uint64_t") {
- fmt = fp.Parse("R64_UINT");
- } else if (data == "float") {
- fmt = fp.Parse("R32_SFLOAT");
- } else if (data == "double") {
- fmt = fp.Parse("R64_SFLOAT");
- } else {
- fmt = MakeUnique<Format>();
- int row_count = 4;
- FormatMode mode = FormatMode::kSFloat;
- uint8_t num_bits = 32;
-
- size_t vec_pos = data.find("vec");
- if (vec_pos != std::string::npos) {
- if (data[0] == 'i') {
- mode = FormatMode::kSInt;
- } else if (data[0] == 'u') {
- mode = FormatMode::kUInt;
- } else if (data[0] == 'd') {
- num_bits = 64;
- }
-
- if (data[1] == '8')
- num_bits = 8;
- else if (data[1] == '1' && data[2] == '6')
- num_bits = 16;
- else if (data[1] == '6' && data[2] == '4')
- num_bits = 64;
-
- if ((vec_pos + 3) < data.length())
- row_count = data[vec_pos + 3] - '0';
-
- } else {
- size_t mat_pos = data.find("mat");
- if (mat_pos == std::string::npos)
- return nullptr;
-
- matrix = true;
+std::unique_ptr<type::Type> DatumTypeParser::Parse(const std::string& data) {
+ TypeParser tp;
+ if (data == "int")
+ return tp.Parse("R32_SINT");
+ if (data == "uint")
+ return tp.Parse("R32_UINT");
+ if (data == "int8_t")
+ return tp.Parse("R8_SINT");
+ if (data == "uint8_t")
+ return tp.Parse("R8_UINT");
+ if (data == "int16_t")
+ return tp.Parse("R16_SINT");
+ if (data == "uint16_t")
+ return tp.Parse("R16_UINT");
+ if (data == "int64_t")
+ return tp.Parse("R64_SINT");
+ if (data == "uint64_t")
+ return tp.Parse("R64_UINT");
+ if (data == "float")
+ return tp.Parse("R32_SFLOAT");
+ if (data == "double")
+ return tp.Parse("R64_SFLOAT");
+
+ int row_count = 4;
+ int column_count = 1;
+ FormatMode mode = FormatMode::kSFloat;
+ uint8_t num_bits = 32;
+ size_t vec_pos = data.find("vec");
+ if (vec_pos != std::string::npos) {
+ if (data[0] == 'i') {
+ mode = FormatMode::kSInt;
+ } else if (data[0] == 'u') {
+ mode = FormatMode::kUInt;
+ } else if (data[0] == 'd') {
+ num_bits = 64;
+ }
- if (data[0] == 'd')
- num_bits = 64;
+ if (data[1] == '8')
+ num_bits = 8;
+ else if (data[1] == '1' && data[2] == '6')
+ num_bits = 16;
+ else if (data[1] == '6' && data[2] == '4')
+ num_bits = 64;
- int column_count = 1;
- if (mat_pos + 3 < data.length())
- column_count = data[mat_pos + 3] - '0';
+ if ((vec_pos + 3) < data.length())
+ row_count = data[vec_pos + 3] - '0';
+ } else {
+ size_t mat_pos = data.find("mat");
+ if (mat_pos == std::string::npos)
+ return nullptr;
- if (mat_pos + 5 < data.length())
- row_count = data[mat_pos + 5] - '0';
- else
- row_count = column_count;
+ if (data[0] == 'd')
+ num_bits = 64;
- fmt->SetColumnCount(static_cast<uint32_t>(column_count));
- }
+ if (mat_pos + 3 < data.length())
+ column_count = data[mat_pos + 3] - '0';
- for (int i = 0; i < row_count; ++i)
- fmt->AddComponent(FORMAT_TYPES[i], mode, num_bits);
+ if (mat_pos + 5 < data.length())
+ row_count = data[mat_pos + 5] - '0';
+ else
+ row_count = column_count;
}
- if (!fmt)
- return nullptr;
-
- // Convert the name back into a FormatType so we can use it in the buffer
- // later Otherwise, we end up with a type of Unknown.
- //
- // There is no equivalent type for a matrix.
- if (!matrix) {
- std::string name = fmt->GenerateName();
- if (name == "")
- return nullptr;
- fmt->SetFormatType(FormatParser::NameToType(name));
- }
- return fmt;
+ std::unique_ptr<type::Type> type;
+ if (mode == FormatMode::kSFloat)
+ type = type::Number::Float(num_bits);
+ else if (mode == FormatMode::kSInt)
+ type = type::Number::Int(num_bits);
+ else
+ type = type::Number::Uint(num_bits);
+
+ type->SetRowCount(static_cast<uint32_t>(row_count));
+ type->SetColumnCount(static_cast<uint32_t>(column_count));
+ return type;
}
} // namespace vkscript
diff --git a/src/vkscript/datum_type_parser.h b/src/vkscript/datum_type_parser.h
index 9d37228..ca01122 100644
--- a/src/vkscript/datum_type_parser.h
+++ b/src/vkscript/datum_type_parser.h
@@ -19,7 +19,7 @@
#include <string>
#include "amber/result.h"
-#include "src/format.h"
+#include "src/type.h"
namespace amber {
namespace vkscript {
@@ -30,7 +30,7 @@ class DatumTypeParser {
DatumTypeParser();
~DatumTypeParser();
- std::unique_ptr<Format> Parse(const std::string& data);
+ std::unique_ptr<type::Type> Parse(const std::string& data);
};
} // namespace vkscript
diff --git a/src/vkscript/datum_type_parser_test.cc b/src/vkscript/datum_type_parser_test.cc
index 23d9eb3..a9d6089 100644
--- a/src/vkscript/datum_type_parser_test.cc
+++ b/src/vkscript/datum_type_parser_test.cc
@@ -15,6 +15,7 @@
#include "src/vkscript/datum_type_parser.h"
#include "gtest/gtest.h"
+#include "src/format.h"
namespace amber {
namespace vkscript {
@@ -24,10 +25,10 @@ bool AllCompsAreType(Format* fmt, FormatMode mode, uint8_t num_bits) {
for (auto& seg : fmt->GetSegments()) {
if (seg.IsPadding())
continue;
- if (seg.GetComponent()->mode != mode ||
- seg.GetComponent()->num_bits != num_bits) {
+ if (seg.GetNumBits() != num_bits)
+ return false;
+ if (seg.GetFormatMode() != mode)
return false;
- }
}
return true;
@@ -39,14 +40,14 @@ using DatumTypeParserTest = testing::Test;
TEST_F(DatumTypeParserTest, EmptyType) {
DatumTypeParser tp;
- auto fmt = tp.Parse("");
- ASSERT_TRUE(fmt == nullptr);
+ auto type = tp.Parse("");
+ ASSERT_TRUE(type == nullptr);
}
TEST_F(DatumTypeParserTest, InvalidType) {
DatumTypeParser tp;
- auto fmt = tp.Parse("INVALID");
- ASSERT_TRUE(fmt == nullptr);
+ auto type = tp.Parse("INVALID");
+ ASSERT_TRUE(type == nullptr);
}
struct DatumTypeData {
@@ -63,12 +64,13 @@ TEST_P(DatumTypeDataTest, Parser) {
const auto& test_data = GetParam();
DatumTypeParser tp;
- auto fmt = tp.Parse(test_data.name);
+ auto type = tp.Parse(test_data.name);
- ASSERT_TRUE(fmt != nullptr);
- EXPECT_TRUE(AllCompsAreType(fmt.get(), test_data.type, test_data.num_bits));
- EXPECT_EQ(test_data.column_count, fmt->ColumnCount());
- EXPECT_EQ(test_data.row_count, fmt->RowCount());
+ ASSERT_TRUE(type != nullptr);
+ Format fmt(type.get());
+ EXPECT_TRUE(AllCompsAreType(&fmt, test_data.type, test_data.num_bits));
+ EXPECT_EQ(test_data.column_count, type->ColumnCount());
+ EXPECT_EQ(test_data.row_count, type->RowCount());
}
INSTANTIATE_TEST_SUITE_P(
@@ -155,10 +157,12 @@ TEST_P(DatumTypeTestFormat, ToFormat) {
auto test_data = GetParam();
DatumTypeParser tp;
- auto fmt = tp.Parse(test_data.name);
+ auto type = tp.Parse(test_data.name);
+
+ ASSERT_TRUE(type != nullptr) << test_data.name;
- ASSERT_TRUE(fmt != nullptr);
- ASSERT_EQ(test_data.format_type, fmt->GetFormatType());
+ Format fmt(type.get());
+ ASSERT_EQ(test_data.format_type, fmt.GetFormatType()) << test_data.name;
}
INSTANTIATE_TEST_SUITE_P(
diff --git a/src/vkscript/parser.cc b/src/vkscript/parser.cc
index 6ae7684..12e94fb 100644
--- a/src/vkscript/parser.cc
+++ b/src/vkscript/parser.cc
@@ -21,9 +21,9 @@
#include <utility>
#include <vector>
-#include "src/format_parser.h"
#include "src/make_unique.h"
#include "src/shader.h"
+#include "src/type_parser.h"
#include "src/vkscript/command_parser.h"
namespace amber {
@@ -169,26 +169,29 @@ Result Parser::ProcessRequireBlock(const SectionParser::Section& section) {
if (!token->IsString())
return Result(make_error(tokenizer, "Missing framebuffer format"));
- FormatParser fmt_parser;
- auto fmt = fmt_parser.Parse(token->AsString());
- if (fmt == nullptr) {
+ TypeParser type_parser;
+ auto type = type_parser.Parse(token->AsString());
+ if (type == nullptr) {
return Result(
make_error(tokenizer, "Failed to parse framebuffer format: " +
token->ToOriginalString()));
}
+
+ auto fmt = MakeUnique<Format>(type.get());
script_->GetPipeline(kDefaultPipelineName)
->GetColorAttachments()[0]
.buffer->SetFormat(fmt.get());
script_->RegisterFormat(std::move(fmt));
+ script_->RegisterType(std::move(type));
} else if (str == "depthstencil") {
token = tokenizer.NextToken();
if (!token->IsString())
return Result(make_error(tokenizer, "Missing depthStencil format"));
- FormatParser fmt_parser;
- auto fmt = fmt_parser.Parse(token->AsString());
- if (fmt == nullptr) {
+ TypeParser type_parser;
+ auto type = type_parser.Parse(token->AsString());
+ if (type == nullptr) {
return Result(
make_error(tokenizer, "Failed to parse depthstencil format: " +
token->ToOriginalString()));
@@ -198,10 +201,12 @@ Result Parser::ProcessRequireBlock(const SectionParser::Section& section) {
if (pipeline->GetDepthBuffer().buffer != nullptr)
return Result("Only one depthstencil command allowed");
+ auto fmt = MakeUnique<Format>(type.get());
// Generate and add a depth buffer
auto depth_buf = pipeline->GenerateDefaultDepthAttachmentBuffer();
depth_buf->SetFormat(fmt.get());
script_->RegisterFormat(std::move(fmt));
+ script_->RegisterType(std::move(type));
Result r = pipeline->SetDepthBuffer(depth_buf.get());
if (!r.IsSuccess())
@@ -290,14 +295,16 @@ Result Parser::ProcessIndicesBlock(const SectionParser::Section& section) {
}
if (!indices.empty()) {
- FormatParser fp;
- auto fmt = fp.Parse("R32_UINT");
+ TypeParser parser;
+ auto type = parser.Parse("R32_UINT");
+ auto fmt = MakeUnique<Format>(type.get());
auto b = MakeUnique<Buffer>(BufferType::kIndex);
auto* buf = b.get();
b->SetName("indices");
b->SetFormat(fmt.get());
b->SetData(std::move(indices));
script_->RegisterFormat(std::move(fmt));
+ script_->RegisterType(std::move(type));
Result r = script_->AddBuffer(std::move(b));
if (!r.IsSuccess())
@@ -325,7 +332,7 @@ Result Parser::ProcessVertexDataBlock(const SectionParser::Section& section) {
// Process the header line.
struct Header {
uint8_t location;
- std::unique_ptr<Format> format;
+ Format* format;
};
std::vector<Header> headers;
while (!token->IsEOL() && !token->IsEOS()) {
@@ -351,15 +358,18 @@ Result Parser::ProcessVertexDataBlock(const SectionParser::Section& section) {
return Result(make_error(tokenizer, "Vertex data format too short: " +
token->ToOriginalString()));
- FormatParser parser;
- auto fmt = parser.Parse(fmt_name.substr(1, fmt_name.length()));
- if (!fmt) {
+ TypeParser parser;
+ auto type = parser.Parse(fmt_name.substr(1, fmt_name.length()));
+ if (!type) {
return Result(
make_error(tokenizer, "Invalid format in vertex data header: " +
fmt_name.substr(1, fmt_name.length())));
}
- headers.push_back({loc, std::move(fmt)});
+ auto fmt = MakeUnique<Format>(type.get());
+ headers.push_back({loc, fmt.get()});
+ script_->RegisterFormat(std::move(fmt));
+ script_->RegisterType(std::move(type));
token = tokenizer.NextToken();
}
@@ -377,7 +387,8 @@ Result Parser::ProcessVertexDataBlock(const SectionParser::Section& section) {
const auto& header = headers[j];
auto& value_data = values[j];
- if (header.format->GetPackSize() > 0) {
+ auto* type = header.format->GetType();
+ if (type->IsList() && type->AsList()->IsPacked()) {
if (!token->IsHex()) {
return Result(
make_error(tokenizer, "Invalid packed value in Vertex Data: " +
@@ -398,11 +409,9 @@ Result Parser::ProcessVertexDataBlock(const SectionParser::Section& section) {
"Too few cells in given vertex data row"));
}
- auto comp = seg.GetComponent();
-
Value v;
- if (comp->mode == FormatMode::kUFloat ||
- comp->mode == FormatMode::kSFloat) {
+ if (seg.GetFormatMode() == FormatMode::kUFloat ||
+ seg.GetFormatMode() == FormatMode::kSFloat) {
Result r = token->ConvertToDouble();
if (!r.IsSuccess())
return r;
@@ -427,10 +436,12 @@ Result Parser::ProcessVertexDataBlock(const SectionParser::Section& section) {
auto buffer = MakeUnique<Buffer>(BufferType::kVertex);
auto* buf = buffer.get();
buffer->SetName("Vertices" + std::to_string(i));
- buffer->SetFormat(headers[i].format.get());
- buffer->SetData(std::move(values[i]));
+ buffer->SetFormat(headers[i].format);
+ Result r = buffer->SetData(std::move(values[i]));
+ if (!r.IsSuccess())
+ return r;
+
script_->AddBuffer(std::move(buffer));
- script_->RegisterFormat(std::move(headers[i].format));
pipeline->AddVertexBuffer(buf, headers[i].location);
}
diff --git a/src/vkscript/parser_test.cc b/src/vkscript/parser_test.cc
index ab072af..676e75e 100644
--- a/src/vkscript/parser_test.cc
+++ b/src/vkscript/parser_test.cc
@@ -385,8 +385,8 @@ TEST_F(VkScriptParserTest, VertexDataHeaderGlslString) {
auto& segs1 = buffers[1]->GetFormat()->GetSegments();
ASSERT_EQ(2U, segs1.size());
- EXPECT_EQ(FormatMode::kSFloat, segs1[0].GetComponent()->mode);
- EXPECT_EQ(FormatMode::kSFloat, segs1[1].GetComponent()->mode);
+ EXPECT_EQ(FormatMode::kSFloat, segs1[0].GetFormatMode());
+ EXPECT_EQ(FormatMode::kSFloat, segs1[1].GetFormatMode());
EXPECT_EQ(static_cast<uint32_t>(0), buffers[1]->ElementCount());
ASSERT_EQ(BufferType::kVertex, buffers[2]->GetBufferType());
@@ -396,9 +396,9 @@ TEST_F(VkScriptParserTest, VertexDataHeaderGlslString) {
auto& segs2 = buffers[2]->GetFormat()->GetSegments();
ASSERT_EQ(4, segs2.size());
- EXPECT_EQ(FormatMode::kSInt, segs2[0].GetComponent()->mode);
- EXPECT_EQ(FormatMode::kSInt, segs2[1].GetComponent()->mode);
- EXPECT_EQ(FormatMode::kSInt, segs2[2].GetComponent()->mode);
+ EXPECT_EQ(FormatMode::kSInt, segs2[0].GetFormatMode());
+ EXPECT_EQ(FormatMode::kSInt, segs2[1].GetFormatMode());
+ EXPECT_EQ(FormatMode::kSInt, segs2[2].GetFormatMode());
EXPECT_TRUE(segs2[3].IsPadding());
EXPECT_EQ(static_cast<uint32_t>(0), buffers[2]->ElementCount());
}
@@ -457,7 +457,6 @@ TEST_F(VkScriptParserTest, VertexDataRows) {
std::vector<float> seg_0 = {-1.f, -1.f, 0.25f, 0, 0.25f, -1.f, 0.25f, 0};
const auto* values_0 = buffers[1]->GetValues<float>();
- ASSERT_EQ(seg_0.size(), buffers[1]->ValueCount());
for (size_t i = 0; i < seg_0.size(); ++i) {
EXPECT_FLOAT_EQ(seg_0[i], values_0[i]);
}
@@ -466,7 +465,6 @@ TEST_F(VkScriptParserTest, VertexDataRows) {
std::vector<uint8_t> seg_1 = {255, 128, 1, 0, 255, 128, 255, 0};
const auto* values_1 = buffers[2]->GetValues<uint8_t>();
- ASSERT_EQ(seg_1.size(), buffers[2]->ValueCount());
for (size_t i = 0; i < seg_1.size(); ++i) {
EXPECT_EQ(seg_1[i], values_1[i]);
}
diff --git a/src/vulkan/engine_vulkan.cc b/src/vulkan/engine_vulkan.cc
index 4689409..f9db6b7 100644
--- a/src/vulkan/engine_vulkan.cc
+++ b/src/vulkan/engine_vulkan.cc
@@ -19,8 +19,8 @@
#include <utility>
#include "amber/amber_vulkan.h"
-#include "src/format_parser.h"
#include "src/make_unique.h"
+#include "src/type_parser.h"
#include "src/vulkan/compute_pipeline.h"
#include "src/vulkan/graphics_pipeline.h"
@@ -408,10 +408,12 @@ Result EngineVulkan::DoDrawRect(const DrawRectCommand* command) {
// Since draw rect command contains its vertex information and it
// does not include a format of vertex buffer, we can choose any
// one that is suitable. We use VK_FORMAT_R32G32_SFLOAT for it.
- FormatParser fp;
- auto fmt = fp.Parse("R32G32_SFLOAT");
+ TypeParser parser;
+ auto type = parser.Parse("R32G32_SFLOAT");
+ Format fmt(type.get());
+
auto buf = MakeUnique<Buffer>();
- buf->SetFormat(fmt.get());
+ buf->SetFormat(&fmt);
buf->SetData(std::move(values));
auto vertex_buffer = MakeUnique<VertexBuffer>(device_.get());
diff --git a/src/vulkan/vertex_buffer_test.cc b/src/vulkan/vertex_buffer_test.cc
index ae170ae..c023d5a 100644
--- a/src/vulkan/vertex_buffer_test.cc
+++ b/src/vulkan/vertex_buffer_test.cc
@@ -19,8 +19,8 @@
#include "amber/value.h"
#include "gtest/gtest.h"
#include "src/format.h"
-#include "src/format_parser.h"
#include "src/make_unique.h"
+#include "src/type_parser.h"
#include "src/vulkan/transfer_buffer.h"
namespace amber {
@@ -97,10 +97,11 @@ TEST_F(VertexBufferTest, R8G8B8A8_UINT) {
values[2].SetIntValue(27);
values[3].SetIntValue(255);
- FormatParser fp;
- auto fmt = fp.Parse("R8G8B8A8_UINT");
+ TypeParser parser;
+ auto type = parser.Parse("R8G8B8A8_UINT");
+ Format fmt(type.get());
+ Result r = SetIntData(0, &fmt, values);
- Result r = SetIntData(0, fmt.get(), values);
const uint8_t* ptr = static_cast<const uint8_t*>(GetVkBufferPtr());
EXPECT_EQ(55, ptr[0]);
EXPECT_EQ(3, ptr[1]);
@@ -115,10 +116,11 @@ TEST_F(VertexBufferTest, R16G16B16A16_UINT) {
values[2].SetIntValue(27);
values[3].SetIntValue(255);
- FormatParser fp;
- auto fmt = fp.Parse("R16G16B16A16_UINT");
+ TypeParser parser;
+ auto type = parser.Parse("R16G16B16A16_UINT");
+ Format fmt(type.get());
+ Result r = SetIntData(0, &fmt, values);
- Result r = SetIntData(0, fmt.get(), values);
const uint16_t* ptr = static_cast<const uint16_t*>(GetVkBufferPtr());
EXPECT_EQ(55, ptr[0]);
EXPECT_EQ(3, ptr[1]);
@@ -133,10 +135,11 @@ TEST_F(VertexBufferTest, R32G32B32A32_UINT) {
values[2].SetIntValue(27);
values[3].SetIntValue(255);
- FormatParser fp;
- auto fmt = fp.Parse("R32G32B32A32_UINT");
+ TypeParser parser;
+ auto type = parser.Parse("R32G32B32A32_UINT");
+ Format fmt(type.get());
+ Result r = SetIntData(0, &fmt, values);
- Result r = SetIntData(0, fmt.get(), values);
const uint32_t* ptr = static_cast<const uint32_t*>(GetVkBufferPtr());
EXPECT_EQ(55, ptr[0]);
EXPECT_EQ(3, ptr[1]);
@@ -151,10 +154,11 @@ TEST_F(VertexBufferTest, R64G64B64A64_UINT) {
values[2].SetIntValue(27);
values[3].SetIntValue(255);
- FormatParser fp;
- auto fmt = fp.Parse("R64G64B64A64_UINT");
+ TypeParser parser;
+ auto type = parser.Parse("R64G64B64A64_UINT");
+ Format fmt(type.get());
+ Result r = SetIntData(0, &fmt, values);
- Result r = SetIntData(0, fmt.get(), values);
const uint64_t* ptr = static_cast<const uint64_t*>(GetVkBufferPtr());
EXPECT_EQ(55, ptr[0]);
EXPECT_EQ(3, ptr[1]);
@@ -169,11 +173,12 @@ TEST_F(VertexBufferTest, R8G8B8A8_SNORM) {
values[2].SetIntValue(static_cast<uint64_t>(-128));
values[3].SetIntValue(127);
- FormatParser fp;
- auto fmt = fp.Parse("R8G8B8A8_SNORM");
-
- Result r = SetIntData(0, fmt.get(), values);
+ TypeParser parser;
+ auto type = parser.Parse("R8G8B8A8_SNORM");
+ Format fmt(type.get());
+ Result r = SetIntData(0, &fmt, values);
const int8_t* ptr = static_cast<const int8_t*>(GetVkBufferPtr());
+
EXPECT_EQ(-55, ptr[0]);
EXPECT_EQ(3, ptr[1]);
EXPECT_EQ(-128, ptr[2]);
@@ -187,10 +192,11 @@ TEST_F(VertexBufferTest, R16G16B16A16_SNORM) {
values[2].SetIntValue(static_cast<uint64_t>(-27));
values[3].SetIntValue(255);
- FormatParser fp;
- auto fmt = fp.Parse("R16G16B16A16_SNORM");
+ TypeParser parser;
+ auto type = parser.Parse("R16G16B16A16_SNORM");
+ Format fmt(type.get());
+ Result r = SetIntData(0, &fmt, values);
- Result r = SetIntData(0, fmt.get(), values);
const int16_t* ptr = static_cast<const int16_t*>(GetVkBufferPtr());
EXPECT_EQ(-55, ptr[0]);
EXPECT_EQ(3, ptr[1]);
@@ -205,10 +211,11 @@ TEST_F(VertexBufferTest, R32G32B32A32_SINT) {
values[2].SetIntValue(static_cast<uint64_t>(-27));
values[3].SetIntValue(255);
- FormatParser fp;
- auto fmt = fp.Parse("R32G32B32A32_SINT");
+ TypeParser parser;
+ auto type = parser.Parse("R32G32B32A32_SINT");
+ Format fmt(type.get());
+ Result r = SetIntData(0, &fmt, values);
- Result r = SetIntData(0, fmt.get(), values);
const int32_t* ptr = static_cast<const int32_t*>(GetVkBufferPtr());
EXPECT_EQ(-55, ptr[0]);
EXPECT_EQ(3, ptr[1]);
@@ -223,10 +230,11 @@ TEST_F(VertexBufferTest, R64G64B64A64_SINT) {
values[2].SetIntValue(static_cast<uint64_t>(-27));
values[3].SetIntValue(255);
- FormatParser fp;
- auto fmt = fp.Parse("R64G64B64A64_SINT");
+ TypeParser parser;
+ auto type = parser.Parse("R64G64B64A64_SINT");
+ Format fmt(type.get());
+ Result r = SetIntData(0, &fmt, values);
- Result r = SetIntData(0, fmt.get(), values);
const int64_t* ptr = static_cast<const int64_t*>(GetVkBufferPtr());
EXPECT_EQ(-55, ptr[0]);
EXPECT_EQ(3, ptr[1]);
@@ -240,10 +248,11 @@ TEST_F(VertexBufferTest, R32G32B32_SFLOAT) {
values[1].SetDoubleValue(14.0);
values[2].SetDoubleValue(0.1171875);
- FormatParser fp;
- auto fmt = fp.Parse("R32G32B32_SFLOAT");
+ TypeParser parser;
+ auto type = parser.Parse("R32G32B32_SFLOAT");
+ Format fmt(type.get());
+ Result r = SetDoubleData(0, &fmt, values);
- Result r = SetDoubleData(0, fmt.get(), values);
const float* ptr = static_cast<const float*>(GetVkBufferPtr());
EXPECT_FLOAT_EQ(-6.0f, ptr[0]);
EXPECT_FLOAT_EQ(14.0f, ptr[1]);
@@ -256,10 +265,11 @@ TEST_F(VertexBufferTest, R64G64B64_SFLOAT) {
values[1].SetDoubleValue(14.0);
values[2].SetDoubleValue(0.1171875);
- FormatParser fp;
- auto fmt = fp.Parse("R64G64B64_SFLOAT");
+ TypeParser parser;
+ auto type = parser.Parse("R64G64B64_SFLOAT");
+ Format fmt(type.get());
+ Result r = SetDoubleData(0, &fmt, values);
- Result r = SetDoubleData(0, fmt.get(), values);
const double* ptr = static_cast<const double*>(GetVkBufferPtr());
EXPECT_DOUBLE_EQ(-6.0, ptr[0]);
EXPECT_DOUBLE_EQ(14.0, ptr[1]);