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