1 //
2 // Copyright 2002 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
7 #include "gtest/gtest.h"
8
9 #include "angle_gl.h"
10 #include "common/angleutils.h"
11 #include "common/utilities.h"
12 #include "compiler/translator/VariablePacker.h"
13
14 namespace
15 {
16
17 static sh::GLenum types[] = {
18 GL_FLOAT_MAT4, // 0
19 GL_FLOAT_MAT2, // 1
20 GL_FLOAT_VEC4, // 2
21 GL_INT_VEC4, // 3
22 GL_BOOL_VEC4, // 4
23 GL_FLOAT_MAT3, // 5
24 GL_FLOAT_VEC3, // 6
25 GL_INT_VEC3, // 7
26 GL_BOOL_VEC3, // 8
27 GL_FLOAT_VEC2, // 9
28 GL_INT_VEC2, // 10
29 GL_BOOL_VEC2, // 11
30 GL_FLOAT, // 12
31 GL_INT, // 13
32 GL_BOOL, // 14
33 GL_SAMPLER_2D, // 15
34 GL_SAMPLER_CUBE, // 16
35 GL_SAMPLER_EXTERNAL_OES, // 17
36 GL_SAMPLER_2D_RECT_ANGLE, // 18
37 GL_UNSIGNED_INT, // 19
38 GL_UNSIGNED_INT_VEC2, // 20
39 GL_UNSIGNED_INT_VEC3, // 21
40 GL_UNSIGNED_INT_VEC4, // 22
41 GL_FLOAT_MAT2x3, // 23
42 GL_FLOAT_MAT2x4, // 24
43 GL_FLOAT_MAT3x2, // 25
44 GL_FLOAT_MAT3x4, // 26
45 GL_FLOAT_MAT4x2, // 27
46 GL_FLOAT_MAT4x3, // 28
47 GL_SAMPLER_3D, // 29
48 GL_SAMPLER_2D_ARRAY, // 30
49 GL_SAMPLER_2D_SHADOW, // 31
50 GL_SAMPLER_CUBE_SHADOW, // 32
51 GL_SAMPLER_2D_ARRAY_SHADOW, // 33
52 GL_INT_SAMPLER_2D, // 34
53 GL_INT_SAMPLER_CUBE, // 35
54 GL_INT_SAMPLER_3D, // 36
55 GL_INT_SAMPLER_2D_ARRAY, // 37
56 GL_UNSIGNED_INT_SAMPLER_2D, // 38
57 GL_UNSIGNED_INT_SAMPLER_CUBE, // 39
58 GL_UNSIGNED_INT_SAMPLER_3D, // 40
59 GL_UNSIGNED_INT_SAMPLER_2D_ARRAY, // 41
60 };
61
62 static sh::GLenum nonSqMatTypes[] = {GL_FLOAT_MAT2x3, GL_FLOAT_MAT2x4, GL_FLOAT_MAT3x2,
63 GL_FLOAT_MAT3x4, GL_FLOAT_MAT4x2, GL_FLOAT_MAT4x3};
64
65 // Creates either a single variable or an array variable depending on numVars.
CreateShaderVariable(sh::GLenum type,int numVars)66 sh::ShaderVariable CreateShaderVariable(sh::GLenum type, int numVars)
67 {
68 ASSERT(numVars != 0);
69 if (numVars == 1)
70 {
71 return sh::ShaderVariable(type);
72 }
73 return sh::ShaderVariable(type, numVars);
74 }
75
76 } // anonymous namespace
77
TEST(VariablePacking,Pack)78 TEST(VariablePacking, Pack)
79 {
80 std::vector<sh::ShaderVariable> vars;
81 const int kMaxRows = 16;
82 // test no vars.
83 EXPECT_TRUE(CheckVariablesInPackingLimits(kMaxRows, vars));
84
85 for (size_t tt = 0; tt < ArraySize(types); ++tt)
86 {
87 sh::GLenum type = types[tt];
88 int num_rows = sh::GetTypePackingRows(type);
89 int num_components_per_row = sh::GetTypePackingComponentsPerRow(type);
90 // Check 1 of the type.
91 vars.clear();
92 vars.push_back(sh::ShaderVariable(type));
93 EXPECT_TRUE(CheckVariablesInPackingLimits(kMaxRows, vars));
94
95 // Check exactly the right amount of 1 type as an array.
96 int num_vars = kMaxRows / num_rows;
97 vars.clear();
98 vars.push_back(CreateShaderVariable(type, num_vars));
99 EXPECT_TRUE(CheckVariablesInPackingLimits(kMaxRows, vars));
100
101 // test too many
102 vars.clear();
103 vars.push_back(CreateShaderVariable(type, num_vars + 1));
104 EXPECT_FALSE(CheckVariablesInPackingLimits(kMaxRows, vars));
105
106 // Check exactly the right amount of 1 type as individual vars.
107 num_vars =
108 kMaxRows / num_rows * ((num_components_per_row > 2) ? 1 : (4 / num_components_per_row));
109 vars.clear();
110 for (int ii = 0; ii < num_vars; ++ii)
111 {
112 vars.push_back(sh::ShaderVariable(type));
113 }
114 EXPECT_TRUE(CheckVariablesInPackingLimits(kMaxRows, vars));
115
116 // Check 1 too many.
117 vars.push_back(sh::ShaderVariable(type));
118 EXPECT_FALSE(CheckVariablesInPackingLimits(kMaxRows, vars));
119 }
120
121 // Test example from GLSL ES 3.0 spec chapter 11.
122 vars.clear();
123 vars.push_back(sh::ShaderVariable(GL_FLOAT_VEC4));
124 vars.push_back(sh::ShaderVariable(GL_FLOAT_MAT3));
125 vars.push_back(sh::ShaderVariable(GL_FLOAT_MAT3));
126 vars.push_back(sh::ShaderVariable(GL_FLOAT_VEC2, 6));
127 vars.push_back(sh::ShaderVariable(GL_FLOAT_VEC2, 4));
128 vars.push_back(sh::ShaderVariable(GL_FLOAT_VEC2));
129 vars.push_back(sh::ShaderVariable(GL_FLOAT, 3));
130 vars.push_back(sh::ShaderVariable(GL_FLOAT, 2));
131 vars.push_back(sh::ShaderVariable(GL_FLOAT));
132 EXPECT_TRUE(CheckVariablesInPackingLimits(kMaxRows, vars));
133 }
134
TEST(VariablePacking,PackSizes)135 TEST(VariablePacking, PackSizes)
136 {
137 for (size_t tt = 0; tt < ArraySize(types); ++tt)
138 {
139 sh::GLenum type = types[tt];
140
141 int expectedComponents = gl::VariableComponentCount(type);
142 int expectedRows = gl::VariableRowCount(type);
143
144 if (type == GL_FLOAT_MAT2)
145 {
146 expectedComponents = 4;
147 }
148 else if (gl::IsMatrixType(type))
149 {
150 int squareSize = std::max(gl::VariableRowCount(type), gl::VariableColumnCount(type));
151 expectedComponents = squareSize;
152 expectedRows = squareSize;
153 }
154
155 EXPECT_EQ(expectedComponents, sh::GetTypePackingComponentsPerRow(type));
156 EXPECT_EQ(expectedRows, sh::GetTypePackingRows(type));
157 }
158 }
159
160 // Check special assumptions about packing non-square mats
TEST(VariablePacking,NonSquareMats)161 TEST(VariablePacking, NonSquareMats)
162 {
163
164 for (size_t mt = 0; mt < ArraySize(nonSqMatTypes); ++mt)
165 {
166
167 sh::GLenum type = nonSqMatTypes[mt];
168
169 int rows = gl::VariableRowCount(type);
170 int cols = gl::VariableColumnCount(type);
171 int squareSize = std::max(rows, cols);
172
173 std::vector<sh::ShaderVariable> vars;
174 vars.push_back(sh::ShaderVariable(type));
175
176 // Fill columns
177 for (int row = 0; row < squareSize; row++)
178 {
179 for (int col = squareSize; col < 4; ++col)
180 {
181 vars.push_back(sh::ShaderVariable(GL_FLOAT));
182 }
183 }
184
185 EXPECT_TRUE(CheckVariablesInPackingLimits(squareSize, vars));
186
187 // and one scalar and packing should fail
188 vars.push_back(sh::ShaderVariable(GL_FLOAT));
189 EXPECT_FALSE(CheckVariablesInPackingLimits(squareSize, vars));
190 }
191 }
192
193 // Scalar type variables can be packed sharing rows with other variables.
TEST(VariablePacking,ReuseRows)194 TEST(VariablePacking, ReuseRows)
195 {
196 std::vector<sh::ShaderVariable> vars;
197 const int kMaxRows = 512;
198
199 // uniform bool u0[129];
200 // uniform bool u1[129];
201 // uniform bool u2[129];
202 // uniform bool u3[129];
203 {
204 int num_arrays = 4;
205 int num_elements_per_array = kMaxRows / num_arrays + 1;
206 for (int ii = 0; ii < num_arrays; ++ii)
207 {
208 vars.push_back(sh::ShaderVariable(GL_BOOL, num_elements_per_array));
209 }
210 EXPECT_TRUE(CheckVariablesInPackingLimits(kMaxRows, vars));
211 }
212
213 vars.clear();
214 // uniform vec2 u0[257];
215 // uniform float u1[257];
216 // uniform int u1[257];
217 {
218 int num_elements_per_array = kMaxRows / 2 + 1;
219 vars.push_back(sh::ShaderVariable(GL_FLOAT_VEC2, num_elements_per_array));
220 vars.push_back(sh::ShaderVariable(GL_FLOAT, num_elements_per_array));
221 vars.push_back(sh::ShaderVariable(GL_INT, num_elements_per_array));
222 EXPECT_TRUE(CheckVariablesInPackingLimits(kMaxRows, vars));
223 }
224 }
225
226 // Check the packer supports and flattens structures.
TEST(VariablePacking,Struct)227 TEST(VariablePacking, Struct)
228 {
229 std::vector<sh::ShaderVariable> fields;
230 const int kMaxRows = 16;
231
232 // Test example from GLSL ES 3.0 spec chapter 11, but with structs
233 std::vector<sh::ShaderVariable> vars;
234 vars.push_back(sh::ShaderVariable(GL_NONE));
235
236 sh::ShaderVariable &parentStruct = vars[0];
237 parentStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT_VEC4));
238 parentStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT_MAT3));
239
240 parentStruct.fields.push_back(sh::ShaderVariable(GL_NONE));
241 sh::ShaderVariable &innerStruct = parentStruct.fields.back();
242 innerStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT_MAT3));
243 innerStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT_VEC2, 6));
244 innerStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT_VEC2, 4));
245
246 parentStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT_VEC2));
247 parentStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT, 3));
248 parentStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT, 2));
249 parentStruct.fields.push_back(sh::ShaderVariable(GL_FLOAT));
250
251 EXPECT_TRUE(CheckVariablesInPackingLimits(kMaxRows, vars));
252 }
253