• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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