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