1 //
2 // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // VaryingPacking_unittest.cpp:
7 // Tests for ANGLE's internal varying packing algorithm.
8 //
9
10 #include <gtest/gtest.h>
11 // 'None' is defined as 'struct None {};' in
12 // third_party/googletest/src/googletest/include/gtest/internal/gtest-type-util.h.
13 // But 'None' is also define as a numberic constant 0L in <X11/X.h>.
14 // So we need to include gtest first to avoid such conflict.
15
16 #include "libANGLE/Program.h"
17 #include "libANGLE/VaryingPacking.h"
18
19 using namespace gl;
20
21 namespace
22 {
23
24 class VaryingPackingTest : public ::testing::TestWithParam<GLuint>
25 {
26 protected:
VaryingPackingTest()27 VaryingPackingTest() {}
28
testVaryingPacking(const std::vector<sh::Varying> & shVaryings,VaryingPacking * varyingPacking)29 bool testVaryingPacking(const std::vector<sh::Varying> &shVaryings,
30 VaryingPacking *varyingPacking)
31 {
32 std::vector<PackedVarying> packedVaryings;
33 for (const auto &shVarying : shVaryings)
34 {
35 packedVaryings.push_back(PackedVarying(shVarying, shVarying.interpolation));
36 }
37
38 InfoLog infoLog;
39 std::vector<std::string> transformFeedbackVaryings;
40
41 return varyingPacking->packUserVaryings(infoLog, packedVaryings);
42 }
43
44 // Uses the "relaxed" ANGLE packing mode.
packVaryings(GLuint maxVaryings,const std::vector<sh::Varying> & shVaryings)45 bool packVaryings(GLuint maxVaryings, const std::vector<sh::Varying> &shVaryings)
46 {
47 VaryingPacking varyingPacking(maxVaryings, PackMode::ANGLE_RELAXED);
48 return testVaryingPacking(shVaryings, &varyingPacking);
49 }
50
51 // Uses the stricter WebGL style packing rules.
packVaryingsStrict(GLuint maxVaryings,const std::vector<sh::Varying> & shVaryings)52 bool packVaryingsStrict(GLuint maxVaryings, const std::vector<sh::Varying> &shVaryings)
53 {
54 VaryingPacking varyingPacking(maxVaryings, PackMode::WEBGL_STRICT);
55 return testVaryingPacking(shVaryings, &varyingPacking);
56 }
57
58 const int kMaxVaryings = GetParam();
59 };
60
MakeVaryings(GLenum type,size_t count,size_t arraySize)61 std::vector<sh::Varying> MakeVaryings(GLenum type, size_t count, size_t arraySize)
62 {
63 std::vector<sh::Varying> varyings;
64
65 for (size_t index = 0; index < count; ++index)
66 {
67 std::stringstream strstr;
68 strstr << type << index;
69
70 sh::Varying varying;
71 varying.type = type;
72 varying.precision = GL_MEDIUM_FLOAT;
73 varying.name = strstr.str();
74 varying.mappedName = strstr.str();
75 if (arraySize > 0)
76 {
77 varying.arraySizes.push_back(static_cast<unsigned int>(arraySize));
78 }
79 varying.staticUse = true;
80 varying.interpolation = sh::INTERPOLATION_FLAT;
81 varying.isInvariant = false;
82
83 varyings.push_back(varying);
84 }
85
86 return varyings;
87 }
88
AddVaryings(std::vector<sh::Varying> * varyings,GLenum type,size_t count,size_t arraySize)89 void AddVaryings(std::vector<sh::Varying> *varyings, GLenum type, size_t count, size_t arraySize)
90 {
91 const auto &newVaryings = MakeVaryings(type, count, arraySize);
92 varyings->insert(varyings->end(), newVaryings.begin(), newVaryings.end());
93 }
94
95 // Test that a single varying can't overflow the packing.
TEST_P(VaryingPackingTest,OneVaryingLargerThanMax)96 TEST_P(VaryingPackingTest, OneVaryingLargerThanMax)
97 {
98 ASSERT_FALSE(packVaryings(1, MakeVaryings(GL_FLOAT_MAT4, 1, 0)));
99 }
100
101 // This will overflow the available varying space.
TEST_P(VaryingPackingTest,MaxPlusOneVaryingVec3)102 TEST_P(VaryingPackingTest, MaxPlusOneVaryingVec3)
103 {
104 ASSERT_FALSE(packVaryings(kMaxVaryings, MakeVaryings(GL_FLOAT_VEC3, kMaxVaryings + 1, 0)));
105 }
106
107 // This will overflow the available varying space.
TEST_P(VaryingPackingTest,MaxPlusOneVaryingVec3Array)108 TEST_P(VaryingPackingTest, MaxPlusOneVaryingVec3Array)
109 {
110 ASSERT_FALSE(packVaryings(kMaxVaryings, MakeVaryings(GL_FLOAT_VEC3, kMaxVaryings / 2 + 1, 2)));
111 }
112
113 // This will overflow the available varying space.
TEST_P(VaryingPackingTest,MaxVaryingVec3AndOneVec2)114 TEST_P(VaryingPackingTest, MaxVaryingVec3AndOneVec2)
115 {
116 std::vector<sh::Varying> varyings = MakeVaryings(GL_FLOAT_VEC3, kMaxVaryings, 0);
117 AddVaryings(&varyings, GL_FLOAT_VEC2, 1, 0);
118 ASSERT_FALSE(packVaryings(kMaxVaryings, varyings));
119 }
120
121 // This should work since two vec2s are packed in a single register.
TEST_P(VaryingPackingTest,MaxPlusOneVaryingVec2)122 TEST_P(VaryingPackingTest, MaxPlusOneVaryingVec2)
123 {
124 ASSERT_TRUE(packVaryings(kMaxVaryings, MakeVaryings(GL_FLOAT_VEC2, kMaxVaryings + 1, 0)));
125 }
126
127 // Same for this one as above.
TEST_P(VaryingPackingTest,TwiceMaxVaryingVec2)128 TEST_P(VaryingPackingTest, TwiceMaxVaryingVec2)
129 {
130 ASSERT_TRUE(packVaryings(kMaxVaryings, MakeVaryings(GL_FLOAT_VEC2, kMaxVaryings * 2, 0)));
131 }
132
133 // This should not work since it overflows available varying space.
TEST_P(VaryingPackingTest,TooManyVaryingVec2)134 TEST_P(VaryingPackingTest, TooManyVaryingVec2)
135 {
136 ASSERT_FALSE(packVaryings(kMaxVaryings, MakeVaryings(GL_FLOAT_VEC2, kMaxVaryings * 2 + 1, 0)));
137 }
138
139 // This should work according to the example GL packing rules - the float varyings are slotted
140 // into the end of the vec3 varying arrays.
TEST_P(VaryingPackingTest,MaxVaryingVec3ArrayAndFloatArrays)141 TEST_P(VaryingPackingTest, MaxVaryingVec3ArrayAndFloatArrays)
142 {
143 std::vector<sh::Varying> varyings = MakeVaryings(GL_FLOAT_VEC3, kMaxVaryings / 2, 2);
144 AddVaryings(&varyings, GL_FLOAT, kMaxVaryings / 2, 2);
145 ASSERT_TRUE(packVaryings(kMaxVaryings, varyings));
146 }
147
148 // This should not work - it has one too many float arrays.
TEST_P(VaryingPackingTest,MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)149 TEST_P(VaryingPackingTest, MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)
150 {
151 std::vector<sh::Varying> varyings = MakeVaryings(GL_FLOAT_VEC3, kMaxVaryings / 2, 2);
152 AddVaryings(&varyings, GL_FLOAT, kMaxVaryings / 2 + 1, 2);
153 ASSERT_FALSE(packVaryings(kMaxVaryings, varyings));
154 }
155
156 // WebGL should fail to pack max+1 vec2 arrays, unlike our more relaxed packing.
TEST_P(VaryingPackingTest,MaxPlusOneMat2VaryingsFailsWebGL)157 TEST_P(VaryingPackingTest, MaxPlusOneMat2VaryingsFailsWebGL)
158 {
159 auto varyings = MakeVaryings(GL_FLOAT_MAT2, kMaxVaryings / 2 + 1, 0);
160 ASSERT_FALSE(packVaryingsStrict(kMaxVaryings, varyings));
161 }
162
163 // Makes separate tests for different values of kMaxVaryings.
164 INSTANTIATE_TEST_SUITE_P(, VaryingPackingTest, ::testing::Values(1, 4, 8));
165
166 } // anonymous namespace
167