// 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/format.h" #include "gtest/gtest.h" #include "src/make_unique.h" #include "src/type_parser.h" namespace amber { using FormatTest = testing::Test; TEST_F(FormatTest, DefaultToStd430) { auto f32 = type::Number::Float(32); Format fmt(f32.get()); EXPECT_EQ(Format::Layout::kStd430, fmt.GetLayout()); } TEST_F(FormatTest, SizeInBytesVector_Std430) { TypeParser parser; auto type = parser.Parse("R32G32B32_SFLOAT"); ASSERT_TRUE(type != nullptr); Format fmt(type.get()); EXPECT_EQ(3U, fmt.InputNeededPerElement()); EXPECT_EQ(16U, fmt.SizeInBytes()); } TEST_F(FormatTest, SizeInBytesMatrix_Std430) { TypeParser parser; auto type = parser.Parse("R32G32B32_SFLOAT"); ASSERT_TRUE(type != nullptr); type->SetColumnCount(3); Format fmt(type.get()); EXPECT_EQ(9U, fmt.InputNeededPerElement()); EXPECT_EQ(48U, fmt.SizeInBytes()); } TEST_F(FormatTest, SizeInBytesMatrix_Std140) { TypeParser parser; auto type = parser.Parse("R32G32_SFLOAT"); ASSERT_TRUE(type != nullptr); type->SetColumnCount(2); Format fmt(type.get()); fmt.SetLayout(Format::Format::Layout::kStd140); EXPECT_EQ(32U, fmt.SizeInBytes()); } struct StdData { const char* name; const char* fmt; uint32_t column_count; bool is_std140; uint32_t size_in_bytes; }; using FormatStdTest = testing::TestWithParam; TEST_P(FormatStdTest, Test) { auto test_data = GetParam(); TypeParser parser; auto type = parser.Parse(test_data.fmt); ASSERT_TRUE(type != nullptr) << test_data.name; type->SetColumnCount(test_data.column_count); Format fmt(type.get()); if (test_data.is_std140) fmt.SetLayout(Format::Format::Layout::kStd140); EXPECT_EQ(test_data.size_in_bytes, fmt.SizeInBytes()) << test_data.name; } INSTANTIATE_TEST_SUITE_P( FormatStdTestSamples, FormatStdTest, testing::Values( StdData{"mat2x2-std140", "R32G32_SFLOAT", 2, true, 32U}, StdData{"mat2x3-std140", "R32G32B32_SFLOAT", 2, true, 32U}, StdData{"mat2x4-std140", "R32G32B32A32_SFLOAT", 2, true, 32U}, StdData{"mat3x2-std140", "R32G32_SFLOAT", 3, true, 48U}, StdData{"mat3x3-std140", "R32G32B32_SFLOAT", 3, true, 48U}, StdData{"mat3x4-std140", "R32G32B32A32_SFLOAT", 3, true, 48U}, StdData{"mat4x2-std140", "R32G32_SFLOAT", 4, true, 64U}, StdData{"mat4x3-std140", "R32G32B32_SFLOAT", 4, true, 64U}, StdData{"mat4x4-std140", "R32G32B32A32_SFLOAT", 4, true, 64U}, StdData{"mat2x2-std430", "R32G32_SFLOAT", 2, false, 16U}, StdData{"mat2x3-std430", "R32G32B32_SFLOAT", 2, false, 32U}, StdData{"mat2x4-std430", "R32G32B32A32_SFLOAT", 2, false, 32U}, StdData{"mat3x2-std430", "R32G32_SFLOAT", 3, false, 24U}, StdData{"mat3x3-std430", "R32G32B32_SFLOAT", 3, false, 48U}, StdData{"mat3x4-std430", "R32G32B32A32_SFLOAT", 3, false, 48U}, StdData{"mat4x2-std430", "R32G32_SFLOAT", 4, false, 32U}, StdData{"mat4x3-std430", "R32G32B32_SFLOAT", 4, false, 64U}, StdData{"mat4x4-std430", "R32G32B32A32_SFLOAT", 4, false, 64U}, StdData{"float-std140", "R32_SFLOAT", 1, true, 4U}, StdData{"float-std430", "R32_SFLOAT", 1, false, 4U})); // NOLINT(whitespace/parens) struct Name { const char* name; }; using FormatNameTest = testing::TestWithParam; 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(); 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(); 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(); 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(); 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(); 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(); 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(); auto f32 = type::Number::Float(32); auto i32 = type::Number::Int(32); x->AddMember(i32.get()); x->AddMember(f32.get()); auto s = MakeUnique(); 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(); auto f32 = type::Number::Float(32); auto i32 = type::Number::Int(32); x->AddMember(i32.get()); x->AddMember(f32.get()); auto s = MakeUnique(); 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 x; // float y; // } TEST_F(FormatTest, SegmentStructWithVec2_Std140) { auto s = MakeUnique(); 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(); 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 x; // float y; // } TEST_F(FormatTest, SegmentStructWithFloatPackedToVec_Std140) { auto s = MakeUnique(); 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(); 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 x; // vec2 y; // } TEST_F(FormatTest, SegmentStructVec3Vec2_Std140) { auto s = MakeUnique(); 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(); 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 x; // float y; // } TEST_F(FormatTest, SegmentStructMat2x2_Std140) { auto s = MakeUnique(); 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(); 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(); auto f32 = type::Number::Float(32); auto i32 = type::Number::Int(32); auto x = MakeUnique(); 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(); auto f32 = type::Number::Float(32); auto i32 = type::Number::Int(32); auto x = MakeUnique(); 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(); 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(); 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(); 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(); 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