• 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(GLint maxVaryings,PackMode packMode,const std::vector<sh::ShaderVariable> & shVaryings)29     bool testVaryingPacking(GLint maxVaryings,
30                             PackMode packMode,
31                             const std::vector<sh::ShaderVariable> &shVaryings)
32     {
33         ProgramMergedVaryings mergedVaryings;
34         for (const sh::ShaderVariable &shVarying : shVaryings)
35         {
36             ProgramVaryingRef ref;
37             ref.frontShader      = &shVarying;
38             ref.backShader       = &shVarying;
39             ref.frontShaderStage = ShaderType::Vertex;
40             ref.backShaderStage  = ShaderType::Fragment;
41             mergedVaryings.push_back(ref);
42         }
43 
44         InfoLog infoLog;
45         std::vector<std::string> transformFeedbackVaryings;
46 
47         VaryingPacking varyingPacking;
48         return varyingPacking.collectAndPackUserVaryings(
49             infoLog, maxVaryings, packMode, ShaderType::Vertex, ShaderType::Fragment,
50             mergedVaryings, transformFeedbackVaryings, false);
51     }
52 
53     // Uses the "relaxed" ANGLE packing mode.
packVaryings(GLint maxVaryings,const std::vector<sh::ShaderVariable> & shVaryings)54     bool packVaryings(GLint maxVaryings, const std::vector<sh::ShaderVariable> &shVaryings)
55     {
56         return testVaryingPacking(maxVaryings, PackMode::ANGLE_RELAXED, shVaryings);
57     }
58 
59     // Uses the stricter WebGL style packing rules.
packVaryingsStrict(GLint maxVaryings,const std::vector<sh::ShaderVariable> & shVaryings)60     bool packVaryingsStrict(GLint maxVaryings, const std::vector<sh::ShaderVariable> &shVaryings)
61     {
62         return testVaryingPacking(maxVaryings, PackMode::WEBGL_STRICT, shVaryings);
63     }
64 
65     const int kMaxVaryings = GetParam();
66 };
67 
MakeVaryings(GLenum type,size_t count,size_t arraySize)68 std::vector<sh::ShaderVariable> MakeVaryings(GLenum type, size_t count, size_t arraySize)
69 {
70     std::vector<sh::ShaderVariable> varyings;
71 
72     for (size_t index = 0; index < count; ++index)
73     {
74         std::stringstream strstr;
75         strstr << type << index;
76 
77         sh::ShaderVariable varying;
78         varying.type       = type;
79         varying.precision  = GL_MEDIUM_FLOAT;
80         varying.name       = strstr.str();
81         varying.mappedName = strstr.str();
82         if (arraySize > 0)
83         {
84             varying.arraySizes.push_back(static_cast<unsigned int>(arraySize));
85         }
86         varying.staticUse     = true;
87         varying.interpolation = sh::INTERPOLATION_FLAT;
88         varying.isInvariant   = false;
89 
90         varyings.push_back(varying);
91     }
92 
93     return varyings;
94 }
95 
AddVaryings(std::vector<sh::ShaderVariable> * varyings,GLenum type,size_t count,size_t arraySize)96 void AddVaryings(std::vector<sh::ShaderVariable> *varyings,
97                  GLenum type,
98                  size_t count,
99                  size_t arraySize)
100 {
101     const auto &newVaryings = MakeVaryings(type, count, arraySize);
102     varyings->insert(varyings->end(), newVaryings.begin(), newVaryings.end());
103 }
104 
105 // Test that a single varying can't overflow the packing.
TEST_P(VaryingPackingTest,OneVaryingLargerThanMax)106 TEST_P(VaryingPackingTest, OneVaryingLargerThanMax)
107 {
108     ASSERT_FALSE(packVaryings(1, MakeVaryings(GL_FLOAT_MAT4, 1, 0)));
109 }
110 
111 // This will overflow the available varying space.
TEST_P(VaryingPackingTest,MaxPlusOneVaryingVec3)112 TEST_P(VaryingPackingTest, MaxPlusOneVaryingVec3)
113 {
114     ASSERT_FALSE(packVaryings(kMaxVaryings, MakeVaryings(GL_FLOAT_VEC3, kMaxVaryings + 1, 0)));
115 }
116 
117 // This will overflow the available varying space.
TEST_P(VaryingPackingTest,MaxPlusOneVaryingVec3Array)118 TEST_P(VaryingPackingTest, MaxPlusOneVaryingVec3Array)
119 {
120     ASSERT_FALSE(packVaryings(kMaxVaryings, MakeVaryings(GL_FLOAT_VEC3, kMaxVaryings / 2 + 1, 2)));
121 }
122 
123 // This will overflow the available varying space.
TEST_P(VaryingPackingTest,MaxVaryingVec3AndOneVec2)124 TEST_P(VaryingPackingTest, MaxVaryingVec3AndOneVec2)
125 {
126     std::vector<sh::ShaderVariable> varyings = MakeVaryings(GL_FLOAT_VEC3, kMaxVaryings, 0);
127     AddVaryings(&varyings, GL_FLOAT_VEC2, 1, 0);
128     ASSERT_FALSE(packVaryings(kMaxVaryings, varyings));
129 }
130 
131 // This should work since two vec2s are packed in a single register.
TEST_P(VaryingPackingTest,MaxPlusOneVaryingVec2)132 TEST_P(VaryingPackingTest, MaxPlusOneVaryingVec2)
133 {
134     ASSERT_TRUE(packVaryings(kMaxVaryings, MakeVaryings(GL_FLOAT_VEC2, kMaxVaryings + 1, 0)));
135 }
136 
137 // Same for this one as above.
TEST_P(VaryingPackingTest,TwiceMaxVaryingVec2)138 TEST_P(VaryingPackingTest, TwiceMaxVaryingVec2)
139 {
140     ASSERT_TRUE(packVaryings(kMaxVaryings, MakeVaryings(GL_FLOAT_VEC2, kMaxVaryings * 2, 0)));
141 }
142 
143 // This should not work since it overflows available varying space.
TEST_P(VaryingPackingTest,TooManyVaryingVec2)144 TEST_P(VaryingPackingTest, TooManyVaryingVec2)
145 {
146     ASSERT_FALSE(packVaryings(kMaxVaryings, MakeVaryings(GL_FLOAT_VEC2, kMaxVaryings * 2 + 1, 0)));
147 }
148 
149 // This should work according to the example GL packing rules - the float varyings are slotted
150 // into the end of the vec3 varying arrays.
TEST_P(VaryingPackingTest,MaxVaryingVec3ArrayAndFloatArrays)151 TEST_P(VaryingPackingTest, MaxVaryingVec3ArrayAndFloatArrays)
152 {
153     std::vector<sh::ShaderVariable> varyings = MakeVaryings(GL_FLOAT_VEC3, kMaxVaryings / 2, 2);
154     AddVaryings(&varyings, GL_FLOAT, kMaxVaryings / 2, 2);
155     ASSERT_TRUE(packVaryings(kMaxVaryings, varyings));
156 }
157 
158 // This should not work - it has one too many float arrays.
TEST_P(VaryingPackingTest,MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)159 TEST_P(VaryingPackingTest, MaxVaryingVec3ArrayAndMaxPlusOneFloatArray)
160 {
161     std::vector<sh::ShaderVariable> varyings = MakeVaryings(GL_FLOAT_VEC3, kMaxVaryings / 2, 2);
162     AddVaryings(&varyings, GL_FLOAT, kMaxVaryings / 2 + 1, 2);
163     ASSERT_FALSE(packVaryings(kMaxVaryings, varyings));
164 }
165 
166 // WebGL should fail to pack max+1 vec2 arrays, unlike our more relaxed packing.
TEST_P(VaryingPackingTest,MaxPlusOneMat2VaryingsFailsWebGL)167 TEST_P(VaryingPackingTest, MaxPlusOneMat2VaryingsFailsWebGL)
168 {
169     auto varyings = MakeVaryings(GL_FLOAT_MAT2, kMaxVaryings / 2 + 1, 0);
170     ASSERT_FALSE(packVaryingsStrict(kMaxVaryings, varyings));
171 }
172 
173 // Makes separate tests for different values of kMaxVaryings.
174 INSTANTIATE_TEST_SUITE_P(, VaryingPackingTest, ::testing::Values(1, 4, 8));
175 
176 }  // anonymous namespace
177