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