• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2015 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 "test_utils/ANGLETest.h"
8 #include "test_utils/gl_raii.h"
9 
10 #include <array>
11 #include <cmath>
12 #include <sstream>
13 
14 using namespace angle;
15 
16 namespace
17 {
18 
19 class SimpleUniformTest : public ANGLETest<>
20 {
21   protected:
SimpleUniformTest()22     SimpleUniformTest()
23     {
24         setWindowWidth(128);
25         setWindowHeight(128);
26         setConfigRedBits(8);
27         setConfigGreenBits(8);
28         setConfigBlueBits(8);
29         setConfigAlphaBits(8);
30     }
31 };
32 
33 // Test that we can get and set a float uniform successfully.
TEST_P(SimpleUniformTest,FloatUniformStateQuery)34 TEST_P(SimpleUniformTest, FloatUniformStateQuery)
35 {
36     constexpr char kFragShader[] = R"(precision mediump float;
37 uniform float uniF;
38 void main() {
39     gl_FragColor = vec4(uniF, 0.0, 0.0, 0.0);
40 })";
41 
42     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Zero(), kFragShader);
43     glUseProgram(program);
44     GLint uniformLocation = glGetUniformLocation(program, "uniF");
45     ASSERT_NE(uniformLocation, -1);
46 
47     GLfloat expected = 1.02f;
48     glUniform1f(uniformLocation, expected);
49 
50     GLfloat f = 0.0f;
51     glGetUniformfv(program, uniformLocation, &f);
52     ASSERT_GL_NO_ERROR();
53     ASSERT_EQ(f, expected);
54 }
55 
56 // Test that we can get and set an int uniform successfully.
TEST_P(SimpleUniformTest,IntUniformStateQuery)57 TEST_P(SimpleUniformTest, IntUniformStateQuery)
58 {
59     constexpr char kFragShader[] = R"(uniform int uniI;
60 void main() {
61     gl_FragColor = vec4(uniI, 0.0, 0.0, 0.0);
62 })";
63 
64     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Zero(), kFragShader);
65     glUseProgram(program);
66 
67     GLint uniformLocation = glGetUniformLocation(program, "uniI");
68     ASSERT_NE(uniformLocation, -1);
69 
70     GLint expected = 4;
71     glUniform1i(uniformLocation, expected);
72 
73     GLint i = 0;
74     glGetUniformiv(program, uniformLocation, &i);
75     ASSERT_GL_NO_ERROR();
76     ASSERT_EQ(i, expected);
77 }
78 
79 // Test that we can get and set a vec2 uniform successfully.
TEST_P(SimpleUniformTest,FloatVec2UniformStateQuery)80 TEST_P(SimpleUniformTest, FloatVec2UniformStateQuery)
81 {
82     constexpr char kFragShader[] = R"(precision mediump float;
83 uniform vec2 uniVec2;
84 void main() {
85     gl_FragColor = vec4(uniVec2, 0.0, 0.0);
86 })";
87 
88     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Zero(), kFragShader);
89     glUseProgram(program);
90 
91     GLint uniformLocation = glGetUniformLocation(program, "uniVec2");
92     ASSERT_NE(uniformLocation, -1);
93 
94     std::vector<GLfloat> expected = {{1.0f, 0.5f}};
95     glUniform2fv(uniformLocation, 1, expected.data());
96 
97     std::vector<GLfloat> floats(2, 0);
98     glGetUniformfv(program, uniformLocation, floats.data());
99     ASSERT_GL_NO_ERROR();
100     ASSERT_EQ(floats, expected);
101 }
102 
103 // Test that we can get and set a vec3 uniform successfully.
TEST_P(SimpleUniformTest,FloatVec3UniformStateQuery)104 TEST_P(SimpleUniformTest, FloatVec3UniformStateQuery)
105 {
106     constexpr char kFragShader[] = R"(precision mediump float;
107 uniform vec3 uniVec3;
108 void main() {
109     gl_FragColor = vec4(uniVec3, 0.0);
110 })";
111 
112     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Zero(), kFragShader);
113     glUseProgram(program);
114 
115     GLint uniformLocation = glGetUniformLocation(program, "uniVec3");
116     ASSERT_NE(uniformLocation, -1);
117 
118     std::vector<GLfloat> expected = {{1.0f, 0.5f, 0.2f}};
119     glUniform3fv(uniformLocation, 1, expected.data());
120 
121     std::vector<GLfloat> floats(3, 0);
122     glGetUniformfv(program, uniformLocation, floats.data());
123     ASSERT_GL_NO_ERROR();
124     ASSERT_EQ(floats, expected);
125 }
126 
127 // Test that we can get and set a vec4 uniform successfully.
TEST_P(SimpleUniformTest,FloatVec4UniformStateQuery)128 TEST_P(SimpleUniformTest, FloatVec4UniformStateQuery)
129 {
130     constexpr char kFragShader[] = R"(precision mediump float;
131 uniform vec4 uniVec4;
132 void main() {
133     gl_FragColor = uniVec4;
134 })";
135 
136     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Zero(), kFragShader);
137     glUseProgram(program);
138 
139     GLint uniformLocation = glGetUniformLocation(program, "uniVec4");
140     ASSERT_NE(uniformLocation, -1);
141 
142     std::vector<GLfloat> expected = {{1.0f, 0.5f, 0.2f, -0.8f}};
143     glUniform4fv(uniformLocation, 1, expected.data());
144 
145     std::vector<GLfloat> floats(4, 0);
146     glGetUniformfv(program, uniformLocation, floats.data());
147     ASSERT_GL_NO_ERROR();
148     ASSERT_EQ(floats, expected);
149 }
150 
151 // Test that we can get and set a 2x2 float Matrix uniform successfully.
TEST_P(SimpleUniformTest,FloatMatrix2UniformStateQuery)152 TEST_P(SimpleUniformTest, FloatMatrix2UniformStateQuery)
153 {
154     constexpr char kFragShader[] = R"(precision mediump float;
155 uniform mat2 umat2;
156 void main() {
157     gl_FragColor = vec4(umat2);
158 })";
159 
160     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Zero(), kFragShader);
161     glUseProgram(program);
162 
163     GLint uniformLocation = glGetUniformLocation(program, "umat2");
164     ASSERT_NE(uniformLocation, -1);
165 
166     std::vector<GLfloat> expected = {{1.0f, 0.5f, 0.2f, -0.8f}};
167     glUniformMatrix2fv(uniformLocation, 1, false, expected.data());
168 
169     std::vector<GLfloat> floats(4, 0);
170     glGetUniformfv(program, uniformLocation, floats.data());
171     ASSERT_GL_NO_ERROR();
172     ASSERT_EQ(floats, expected);
173 }
174 
175 // Test that we can get and set a 3x3 float Matrix uniform successfully.
TEST_P(SimpleUniformTest,FloatMatrix3UniformStateQuery)176 TEST_P(SimpleUniformTest, FloatMatrix3UniformStateQuery)
177 {
178     constexpr char kFragShader[] = R"(precision mediump float;
179 uniform mat3 umat3;
180 void main() {
181     gl_FragColor = vec4(umat3);
182 })";
183 
184     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Zero(), kFragShader);
185     glUseProgram(program);
186 
187     GLint uniformLocation = glGetUniformLocation(program, "umat3");
188     ASSERT_NE(uniformLocation, -1);
189 
190     std::vector<GLfloat> expected = {{1.0f, 0.5f, 0.2f, -0.8f, -0.2f, 0.1f, 0.1f, 0.2f, 0.7f}};
191     glUniformMatrix3fv(uniformLocation, 1, false, expected.data());
192 
193     std::vector<GLfloat> floats(9, 0);
194     glGetUniformfv(program, uniformLocation, floats.data());
195     ASSERT_GL_NO_ERROR();
196     ASSERT_EQ(floats, expected);
197 }
198 
199 // Test that we can get and set a 4x4 float Matrix uniform successfully.
TEST_P(SimpleUniformTest,FloatMatrix4UniformStateQuery)200 TEST_P(SimpleUniformTest, FloatMatrix4UniformStateQuery)
201 {
202     constexpr char kFragShader[] = R"(precision mediump float;
203 uniform mat4 umat4;
204 void main() {
205     gl_FragColor = umat4 * vec4(1.0, 1.0, 1.0, 1.0);
206 })";
207 
208     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Zero(), kFragShader);
209     glUseProgram(program);
210 
211     GLint uniformLocation = glGetUniformLocation(program, "umat4");
212     ASSERT_NE(uniformLocation, -1);
213 
214     std::vector<GLfloat> expected = {{1.0f, 0.5f, 0.2f, -0.8f, -0.2f, 0.1f, 0.1f, 0.2f, 0.7f, 0.1f,
215                                       0.7f, 0.1f, 0.7f, 0.1f, 0.7f, 0.1f}};
216     glUniformMatrix4fv(uniformLocation, 1, false, expected.data());
217 
218     std::vector<GLfloat> floats(16, 0);
219     glGetUniformfv(program, uniformLocation, floats.data());
220     ASSERT_GL_NO_ERROR();
221     ASSERT_EQ(floats, expected);
222 }
223 
224 // Test that we can get and set a float array of uniforms.
TEST_P(SimpleUniformTest,FloatArrayUniformStateQuery)225 TEST_P(SimpleUniformTest, FloatArrayUniformStateQuery)
226 {
227 
228     constexpr char kFragShader[] = R"(
229 precision mediump float;
230 uniform float ufloats[4];
231 void main() {
232     gl_FragColor = vec4(ufloats[0], ufloats[1], ufloats[2], ufloats[3]);
233 })";
234 
235     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Zero(), kFragShader);
236     glUseProgram(program);
237     std::vector<GLfloat> expected = {{0.1f, 0.2f, 0.3f, 0.4f}};
238 
239     for (size_t i = 0; i < expected.size(); i++)
240     {
241         std::string locationName = "ufloats[" + std::to_string(i) + "]";
242         GLint uniformLocation    = glGetUniformLocation(program, locationName.c_str());
243         glUniform1f(uniformLocation, expected[i]);
244         ASSERT_GL_NO_ERROR();
245         ASSERT_NE(uniformLocation, -1);
246 
247         GLfloat result = 0;
248         glGetUniformfv(program, uniformLocation, &result);
249         ASSERT_GL_NO_ERROR();
250         ASSERT_EQ(result, expected[i]);
251     }
252 }
253 
254 // Test that we can get and set an array of matrices uniform.
TEST_P(SimpleUniformTest,ArrayOfMat3UniformStateQuery)255 TEST_P(SimpleUniformTest, ArrayOfMat3UniformStateQuery)
256 {
257     constexpr char kFragShader[] = R"(
258 precision mediump float;
259 uniform mat3 umatarray[2];
260 void main() {
261     gl_FragColor = vec4(umatarray[1]);
262 })";
263 
264     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Zero(), kFragShader);
265     glUseProgram(program);
266     std::vector<std::vector<GLfloat>> expected = {
267         {1.0f, 0.5f, 0.2f, -0.8f, -0.2f, 0.1f, 0.1f, 0.2f, 0.7f},
268         {0.9f, 0.4f, 0.1f, -0.9f, -0.3f, 0.0f, 0.0f, 0.1f, 0.6f}};
269 
270     for (size_t i = 0; i < expected.size(); i++)
271     {
272         std::string locationName = "umatarray[" + std::to_string(i) + "]";
273         GLint uniformLocation    = glGetUniformLocation(program, locationName.c_str());
274         glUniformMatrix3fv(uniformLocation, 1, false, expected[i].data());
275         ASSERT_GL_NO_ERROR();
276         ASSERT_NE(uniformLocation, -1);
277 
278         std::vector<GLfloat> results(9, 0);
279         glGetUniformfv(program, uniformLocation, results.data());
280         ASSERT_GL_NO_ERROR();
281         ASSERT_EQ(results, expected[i]);
282     }
283 }
284 
285 // Test that we can get and set an int array of uniforms.
TEST_P(SimpleUniformTest,FloatIntUniformStateQuery)286 TEST_P(SimpleUniformTest, FloatIntUniformStateQuery)
287 {
288 
289     constexpr char kFragShader[] = R"(
290 precision mediump float;
291 uniform int uints[4];
292 void main() {
293     gl_FragColor = vec4(uints[0], uints[1], uints[2], uints[3]);
294 })";
295 
296     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Zero(), kFragShader);
297     glUseProgram(program);
298     std::vector<GLint> expected = {{1, 2, 3, 4}};
299 
300     for (size_t i = 0; i < expected.size(); i++)
301     {
302         std::string locationName = "uints[" + std::to_string(i) + "]";
303         GLint uniformLocation    = glGetUniformLocation(program, locationName.c_str());
304         glUniform1i(uniformLocation, expected[i]);
305         ASSERT_GL_NO_ERROR();
306         ASSERT_NE(uniformLocation, -1);
307 
308         GLint result = 0;
309         glGetUniformiv(program, uniformLocation, &result);
310         ASSERT_GL_NO_ERROR();
311         ASSERT_EQ(result, expected[i]);
312     }
313 }
314 
315 class UniformTest : public ANGLETest<>
316 {
317   protected:
UniformTest()318     UniformTest() : mProgram(0), mUniformFLocation(-1), mUniformILocation(-1), mUniformBLocation(-1)
319     {
320         setWindowWidth(128);
321         setWindowHeight(128);
322         setConfigRedBits(8);
323         setConfigGreenBits(8);
324         setConfigBlueBits(8);
325         setConfigAlphaBits(8);
326     }
327 
testSetUp()328     void testSetUp() override
329     {
330         // TODO(anglebug.com/5505): asserting with latest direct-to-Metal compiler
331         // changes. Must skip all tests explicitly.
332         // if (IsMetal())
333         //    return;
334 
335         constexpr char kVS[] = "void main() { gl_Position = vec4(1); }";
336         constexpr char kFS[] =
337             "precision mediump float;\n"
338             "uniform float uniF;\n"
339             "uniform int uniI;\n"
340             "uniform bool uniB;\n"
341             "uniform bool uniBArr[4];\n"
342             "void main() {\n"
343             "  gl_FragColor = vec4(uniF + float(uniI));\n"
344             "  gl_FragColor += vec4(uniB ? 1.0 : 0.0);\n"
345             "  gl_FragColor += vec4(uniBArr[0] ? 1.0 : 0.0);\n"
346             "  gl_FragColor += vec4(uniBArr[1] ? 1.0 : 0.0);\n"
347             "  gl_FragColor += vec4(uniBArr[2] ? 1.0 : 0.0);\n"
348             "  gl_FragColor += vec4(uniBArr[3] ? 1.0 : 0.0);\n"
349             "}";
350 
351         mProgram = CompileProgram(kVS, kFS);
352         ASSERT_NE(mProgram, 0u);
353 
354         mUniformFLocation = glGetUniformLocation(mProgram, "uniF");
355         ASSERT_NE(mUniformFLocation, -1);
356 
357         mUniformILocation = glGetUniformLocation(mProgram, "uniI");
358         ASSERT_NE(mUniformILocation, -1);
359 
360         mUniformBLocation = glGetUniformLocation(mProgram, "uniB");
361         ASSERT_NE(mUniformBLocation, -1);
362 
363         ASSERT_GL_NO_ERROR();
364     }
365 
testTearDown()366     void testTearDown() override { glDeleteProgram(mProgram); }
367 
368     GLuint mProgram;
369     GLint mUniformFLocation;
370     GLint mUniformILocation;
371     GLint mUniformBLocation;
372 };
373 
TEST_P(UniformTest,GetUniformNoCurrentProgram)374 TEST_P(UniformTest, GetUniformNoCurrentProgram)
375 {
376 
377     glUseProgram(mProgram);
378     glUniform1f(mUniformFLocation, 1.0f);
379     glUniform1i(mUniformILocation, 1);
380     glUseProgram(0);
381 
382     GLfloat f;
383     glGetnUniformfvEXT(mProgram, mUniformFLocation, 4, &f);
384     ASSERT_GL_NO_ERROR();
385     EXPECT_EQ(1.0f, f);
386 
387     glGetUniformfv(mProgram, mUniformFLocation, &f);
388     ASSERT_GL_NO_ERROR();
389     EXPECT_EQ(1.0f, f);
390 
391     GLint i;
392     glGetnUniformivEXT(mProgram, mUniformILocation, 4, &i);
393     ASSERT_GL_NO_ERROR();
394     EXPECT_EQ(1, i);
395 
396     glGetUniformiv(mProgram, mUniformILocation, &i);
397     ASSERT_GL_NO_ERROR();
398     EXPECT_EQ(1, i);
399 }
400 
TEST_P(UniformTest,UniformArrayLocations)401 TEST_P(UniformTest, UniformArrayLocations)
402 {
403 
404     constexpr char kVS[] = R"(precision mediump float;
405 uniform float uPosition[4];
406 void main(void)
407 {
408     gl_Position = vec4(uPosition[0], uPosition[1], uPosition[2], uPosition[3]);
409 })";
410 
411     constexpr char kFS[] = R"(precision mediump float;
412 uniform float uColor[4];
413 void main(void)
414 {
415     gl_FragColor = vec4(uColor[0], uColor[1], uColor[2], uColor[3]);
416 })";
417 
418     ANGLE_GL_PROGRAM(program, kVS, kFS);
419 
420     // Array index zero should be equivalent to the un-indexed uniform
421     EXPECT_NE(-1, glGetUniformLocation(program, "uPosition"));
422     EXPECT_EQ(glGetUniformLocation(program, "uPosition"),
423               glGetUniformLocation(program, "uPosition[0]"));
424 
425     EXPECT_NE(-1, glGetUniformLocation(program, "uColor"));
426     EXPECT_EQ(glGetUniformLocation(program, "uColor"), glGetUniformLocation(program, "uColor[0]"));
427 
428     // All array uniform locations should be unique
429     GLint positionLocations[4] = {
430         glGetUniformLocation(program, "uPosition[0]"),
431         glGetUniformLocation(program, "uPosition[1]"),
432         glGetUniformLocation(program, "uPosition[2]"),
433         glGetUniformLocation(program, "uPosition[3]"),
434     };
435 
436     GLint colorLocations[4] = {
437         glGetUniformLocation(program, "uColor[0]"),
438         glGetUniformLocation(program, "uColor[1]"),
439         glGetUniformLocation(program, "uColor[2]"),
440         glGetUniformLocation(program, "uColor[3]"),
441     };
442 
443     for (size_t i = 0; i < 4; i++)
444     {
445         EXPECT_NE(-1, positionLocations[i]);
446         EXPECT_NE(-1, colorLocations[i]);
447 
448         for (size_t j = i + 1; j < 4; j++)
449         {
450             EXPECT_NE(positionLocations[i], positionLocations[j]);
451             EXPECT_NE(colorLocations[i], colorLocations[j]);
452         }
453     }
454 
455     glDeleteProgram(program);
456 }
457 
458 // Test that float to integer GetUniform rounds values correctly.
TEST_P(UniformTest,FloatUniformStateQuery)459 TEST_P(UniformTest, FloatUniformStateQuery)
460 {
461 
462     std::vector<double> inValues;
463     std::vector<GLfloat> expectedFValues;
464     std::vector<GLint> expectedIValues;
465 
466     double intMaxD = static_cast<double>(std::numeric_limits<GLint>::max());
467     double intMinD = static_cast<double>(std::numeric_limits<GLint>::min());
468 
469     // TODO(jmadill): Investigate rounding of .5
470     inValues.push_back(-1.0);
471     inValues.push_back(-0.6);
472     // inValues.push_back(-0.5); // undefined behaviour?
473     inValues.push_back(-0.4);
474     inValues.push_back(0.0);
475     inValues.push_back(0.4);
476     // inValues.push_back(0.5); // undefined behaviour?
477     inValues.push_back(0.6);
478     inValues.push_back(1.0);
479     inValues.push_back(999999.2);
480     inValues.push_back(intMaxD * 2.0);
481     inValues.push_back(intMaxD + 1.0);
482     inValues.push_back(intMinD * 2.0);
483     inValues.push_back(intMinD - 1.0);
484 
485     for (double value : inValues)
486     {
487         expectedFValues.push_back(static_cast<GLfloat>(value));
488 
489         double clampedValue = std::max(intMinD, std::min(intMaxD, value));
490         double rounded      = round(clampedValue);
491         expectedIValues.push_back(static_cast<GLint>(rounded));
492     }
493 
494     glUseProgram(mProgram);
495     ASSERT_GL_NO_ERROR();
496 
497     for (size_t index = 0; index < inValues.size(); ++index)
498     {
499         GLfloat inValue       = static_cast<GLfloat>(inValues[index]);
500         GLfloat expectedValue = expectedFValues[index];
501 
502         glUniform1f(mUniformFLocation, inValue);
503         GLfloat testValue;
504         glGetUniformfv(mProgram, mUniformFLocation, &testValue);
505         ASSERT_GL_NO_ERROR();
506         EXPECT_EQ(expectedValue, testValue);
507     }
508 
509     for (size_t index = 0; index < inValues.size(); ++index)
510     {
511         GLfloat inValue     = static_cast<GLfloat>(inValues[index]);
512         GLint expectedValue = expectedIValues[index];
513 
514         glUniform1f(mUniformFLocation, inValue);
515         GLint testValue;
516         glGetUniformiv(mProgram, mUniformFLocation, &testValue);
517         ASSERT_GL_NO_ERROR();
518         EXPECT_EQ(expectedValue, testValue);
519     }
520 }
521 
522 // Test that integer to float GetUniform rounds values correctly.
TEST_P(UniformTest,IntUniformStateQuery)523 TEST_P(UniformTest, IntUniformStateQuery)
524 {
525     // Qualcomm seems to have a bug where integer uniforms are internally stored as float, and
526     // large values are rounded to the nearest float representation of an integer.
527     // TODO(jmadill): Lift this suppression when/if the bug is fixed.
528     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
529 
530     std::vector<GLint> inValues;
531     std::vector<GLint> expectedIValues;
532     std::vector<GLfloat> expectedFValues;
533 
534     GLint intMax = std::numeric_limits<GLint>::max();
535     GLint intMin = std::numeric_limits<GLint>::min();
536 
537     inValues.push_back(-1);
538     inValues.push_back(0);
539     inValues.push_back(1);
540     inValues.push_back(999999);
541     inValues.push_back(intMax);
542     inValues.push_back(intMax - 1);
543     inValues.push_back(intMin);
544     inValues.push_back(intMin + 1);
545 
546     for (GLint value : inValues)
547     {
548         expectedIValues.push_back(value);
549         expectedFValues.push_back(static_cast<GLfloat>(value));
550     }
551 
552     glUseProgram(mProgram);
553     ASSERT_GL_NO_ERROR();
554 
555     for (size_t index = 0; index < inValues.size(); ++index)
556     {
557         GLint inValue       = inValues[index];
558         GLint expectedValue = expectedIValues[index];
559 
560         glUniform1i(mUniformILocation, inValue);
561         GLint testValue = 1234567;
562         glGetUniformiv(mProgram, mUniformILocation, &testValue);
563         ASSERT_GL_NO_ERROR();
564         EXPECT_EQ(expectedValue, testValue) << " with glGetUniformiv";
565     }
566 
567     for (size_t index = 0; index < inValues.size(); ++index)
568     {
569         GLint inValue         = inValues[index];
570         GLfloat expectedValue = expectedFValues[index];
571 
572         glUniform1i(mUniformILocation, inValue);
573         GLfloat testValue = 124567.0;
574         glGetUniformfv(mProgram, mUniformILocation, &testValue);
575         ASSERT_GL_NO_ERROR();
576         EXPECT_EQ(expectedValue, testValue) << " with glGetUniformfv";
577     }
578 }
579 
580 // Test that queries of boolean uniforms round correctly.
TEST_P(UniformTest,BooleanUniformStateQuery)581 TEST_P(UniformTest, BooleanUniformStateQuery)
582 {
583 
584     glUseProgram(mProgram);
585     GLint intValue     = 0;
586     GLfloat floatValue = 0.0f;
587 
588     // Calling Uniform1i
589     glUniform1i(mUniformBLocation, GL_FALSE);
590 
591     glGetUniformiv(mProgram, mUniformBLocation, &intValue);
592     EXPECT_EQ(0, intValue);
593 
594     glGetUniformfv(mProgram, mUniformBLocation, &floatValue);
595     EXPECT_EQ(0.0f, floatValue);
596 
597     glUniform1i(mUniformBLocation, GL_TRUE);
598 
599     glGetUniformiv(mProgram, mUniformBLocation, &intValue);
600     EXPECT_EQ(1, intValue);
601 
602     glGetUniformfv(mProgram, mUniformBLocation, &floatValue);
603     EXPECT_EQ(1.0f, floatValue);
604 
605     // Calling Uniform1f
606     glUniform1f(mUniformBLocation, 0.0f);
607 
608     glGetUniformiv(mProgram, mUniformBLocation, &intValue);
609     EXPECT_EQ(0, intValue);
610 
611     glGetUniformfv(mProgram, mUniformBLocation, &floatValue);
612     EXPECT_EQ(0.0f, floatValue);
613 
614     glUniform1f(mUniformBLocation, 1.0f);
615 
616     glGetUniformiv(mProgram, mUniformBLocation, &intValue);
617     EXPECT_EQ(1, intValue);
618 
619     glGetUniformfv(mProgram, mUniformBLocation, &floatValue);
620     EXPECT_EQ(1.0f, floatValue);
621 
622     ASSERT_GL_NO_ERROR();
623 }
624 
625 // Test queries for arrays of boolean uniforms.
TEST_P(UniformTest,BooleanArrayUniformStateQuery)626 TEST_P(UniformTest, BooleanArrayUniformStateQuery)
627 {
628 
629     glUseProgram(mProgram);
630     GLint boolValuesi[4]   = {0, 1, 0, 1};
631     GLfloat boolValuesf[4] = {0, 1, 0, 1};
632 
633     GLint locations[4] = {
634         glGetUniformLocation(mProgram, "uniBArr"),
635         glGetUniformLocation(mProgram, "uniBArr[1]"),
636         glGetUniformLocation(mProgram, "uniBArr[2]"),
637         glGetUniformLocation(mProgram, "uniBArr[3]"),
638     };
639 
640     for (int i = 0; i < 4; ++i)
641     {
642         ASSERT_NE(-1, locations[i]) << " with i=" << i;
643     }
644 
645     // Calling Uniform1iv
646     glUniform1iv(locations[0], 4, boolValuesi);
647 
648     for (unsigned int idx = 0; idx < 4; ++idx)
649     {
650         int value = -1;
651         glGetUniformiv(mProgram, locations[idx], &value);
652         EXPECT_EQ(boolValuesi[idx], value) << " with Uniform1iv/GetUniformiv at " << idx;
653     }
654 
655     for (unsigned int idx = 0; idx < 4; ++idx)
656     {
657         float value = -1.0f;
658         glGetUniformfv(mProgram, locations[idx], &value);
659         EXPECT_EQ(boolValuesf[idx], value) << " with Uniform1iv/GetUniformfv at " << idx;
660     }
661 
662     // Calling Uniform1fv
663     glUniform1fv(locations[0], 4, boolValuesf);
664 
665     for (unsigned int idx = 0; idx < 4; ++idx)
666     {
667         int value = -1;
668         glGetUniformiv(mProgram, locations[idx], &value);
669         EXPECT_EQ(boolValuesi[idx], value) << " with Uniform1fv/GetUniformiv at " << idx;
670     }
671 
672     for (unsigned int idx = 0; idx < 4; ++idx)
673     {
674         float value = -1.0f;
675         glGetUniformfv(mProgram, locations[idx], &value);
676         EXPECT_EQ(boolValuesf[idx], value) << " with Uniform1fv/GetUniformfv at " << idx;
677     }
678 
679     ASSERT_GL_NO_ERROR();
680 }
681 
682 class UniformTestES3 : public ANGLETest<>
683 {
684   protected:
UniformTestES3()685     UniformTestES3() : mProgram(0) {}
686 
testTearDown()687     void testTearDown() override
688     {
689         if (mProgram != 0)
690         {
691             glDeleteProgram(mProgram);
692             mProgram = 0;
693         }
694     }
695 
696     GLuint mProgram;
697 };
698 
699 // Test that we can get and set an array of matrices uniform.
TEST_P(UniformTestES3,MatrixArrayUniformStateQuery)700 TEST_P(UniformTestES3, MatrixArrayUniformStateQuery)
701 {
702     constexpr char kFragShader[] =
703         "#version 300 es\n"
704         "precision mediump float;\n"
705         "uniform mat3x4 uniMat3x4[5];\n"
706         "out vec4 fragColor;\n"
707         "void main() {\n"
708         "    fragColor = vec4(uniMat3x4[0]);\n"
709         "    fragColor += vec4(uniMat3x4[1]);\n"
710         "    fragColor += vec4(uniMat3x4[2]);\n"
711         "    fragColor += vec4(uniMat3x4[3]);\n"
712         "    fragColor += vec4(uniMat3x4[4]);\n"
713         "}\n";
714     constexpr unsigned int kArrayCount   = 5;
715     constexpr unsigned int kMatrixStride = 3 * 4;
716 
717     mProgram = CompileProgram(essl3_shaders::vs::Zero(), kFragShader);
718     ASSERT_NE(mProgram, 0u);
719 
720     glUseProgram(mProgram);
721     GLfloat expected[kArrayCount][kMatrixStride] = {
722         {0.6f, -0.4f, 0.6f, 0.9f, -0.6f, 0.3f, -0.3f, -0.1f, -0.4f, -0.3f, 0.7f, 0.1f},
723         {-0.4f, -0.4f, -0.5f, -0.7f, 0.1f, -0.5f, 0.0f, -0.9f, -0.4f, 0.8f, -0.6f, 0.9f},
724         {0.4f, 0.1f, -0.9f, 1.0f, -0.8f, 0.4f, -0.2f, 0.4f, -0.0f, 0.2f, 0.9f, -0.3f},
725         {0.5f, 0.7f, -0.0f, 1.0f, 0.7f, 0.7f, 0.7f, -0.7f, -0.8f, 0.6f, 0.5f, -0.2f},
726         {-1.0f, 0.8f, 1.0f, -0.4f, 0.7f, 0.5f, 0.5f, 0.8f, 0.6f, 0.1f, 0.4f, -0.9f}};
727 
728     GLint baseLocation = glGetUniformLocation(mProgram, "uniMat3x4");
729     ASSERT_NE(-1, baseLocation);
730 
731     glUniformMatrix3x4fv(baseLocation, kArrayCount, GL_FALSE, &expected[0][0]);
732 
733     for (size_t i = 0; i < kArrayCount; i++)
734     {
735         std::stringstream nameStr;
736         nameStr << "uniMat3x4[" << i << "]";
737         std::string name = nameStr.str();
738         GLint location   = glGetUniformLocation(mProgram, name.c_str());
739         ASSERT_GL_NO_ERROR();
740         ASSERT_NE(-1, location);
741 
742         std::vector<GLfloat> results(12, 0);
743         glGetUniformfv(mProgram, location, results.data());
744         ASSERT_GL_NO_ERROR();
745 
746         for (size_t compIdx = 0; compIdx < kMatrixStride; compIdx++)
747         {
748             EXPECT_EQ(results[compIdx], expected[i][compIdx]);
749         }
750     }
751 }
752 
753 // Test queries for transposed arrays of non-square matrix uniforms.
TEST_P(UniformTestES3,TransposedMatrixArrayUniformStateQuery)754 TEST_P(UniformTestES3, TransposedMatrixArrayUniformStateQuery)
755 {
756     constexpr char kFS[] =
757         "#version 300 es\n"
758         "precision mediump float;\n"
759         "uniform mat3x2 uniMat3x2[5];\n"
760         "out vec4 color;\n"
761         "void main() {\n"
762         "  color = vec4(uniMat3x2[0][0][0]);\n"
763         "  color += vec4(uniMat3x2[1][0][0]);\n"
764         "  color += vec4(uniMat3x2[2][0][0]);\n"
765         "  color += vec4(uniMat3x2[3][0][0]);\n"
766         "  color += vec4(uniMat3x2[4][0][0]);\n"
767         "}";
768 
769     mProgram = CompileProgram(essl3_shaders::vs::Zero(), kFS);
770     ASSERT_NE(mProgram, 0u);
771 
772     glUseProgram(mProgram);
773 
774     std::vector<GLfloat> transposedValues;
775 
776     for (size_t arrayElement = 0; arrayElement < 5; ++arrayElement)
777     {
778         transposedValues.push_back(1.0f + arrayElement);
779         transposedValues.push_back(3.0f + arrayElement);
780         transposedValues.push_back(5.0f + arrayElement);
781         transposedValues.push_back(2.0f + arrayElement);
782         transposedValues.push_back(4.0f + arrayElement);
783         transposedValues.push_back(6.0f + arrayElement);
784     }
785 
786     // Setting as a clump
787     GLint baseLocation = glGetUniformLocation(mProgram, "uniMat3x2");
788     ASSERT_NE(-1, baseLocation);
789 
790     glUniformMatrix3x2fv(baseLocation, 5, GL_TRUE, &transposedValues[0]);
791 
792     for (size_t arrayElement = 0; arrayElement < 5; ++arrayElement)
793     {
794         std::stringstream nameStr;
795         nameStr << "uniMat3x2[" << arrayElement << "]";
796         std::string name = nameStr.str();
797         GLint location   = glGetUniformLocation(mProgram, name.c_str());
798         ASSERT_NE(-1, location);
799 
800         std::vector<GLfloat> sequentialValues(6, 0);
801         glGetUniformfv(mProgram, location, &sequentialValues[0]);
802 
803         ASSERT_GL_NO_ERROR();
804 
805         for (size_t comp = 0; comp < 6; ++comp)
806         {
807             EXPECT_EQ(static_cast<GLfloat>(comp + 1 + arrayElement), sequentialValues[comp]);
808         }
809     }
810 }
811 
812 // Check that trying setting too many elements of an array doesn't overflow
TEST_P(UniformTestES3,OverflowArray)813 TEST_P(UniformTestES3, OverflowArray)
814 {
815 
816     constexpr char kFS[] =
817         "#version 300 es\n"
818         "precision mediump float;\n"
819         "uniform float uniF[5];\n"
820         "uniform mat3x2 uniMat3x2[5];\n"
821         "out vec4 color;\n"
822         "void main() {\n"
823         "  color = vec4(uniMat3x2[0][0][0] + uniF[0]);\n"
824         "  color = vec4(uniMat3x2[1][0][0] + uniF[1]);\n"
825         "  color = vec4(uniMat3x2[2][0][0] + uniF[2]);\n"
826         "  color = vec4(uniMat3x2[3][0][0] + uniF[3]);\n"
827         "  color = vec4(uniMat3x2[4][0][0] + uniF[4]);\n"
828         "}";
829 
830     mProgram = CompileProgram(essl3_shaders::vs::Zero(), kFS);
831     ASSERT_NE(mProgram, 0u);
832 
833     glUseProgram(mProgram);
834 
835     const size_t kOverflowSize = 10000;
836     std::vector<GLfloat> values(10000 * 6);
837 
838     // Setting as a clump
839     GLint floatLocation = glGetUniformLocation(mProgram, "uniF");
840     ASSERT_NE(-1, floatLocation);
841     GLint matLocation = glGetUniformLocation(mProgram, "uniMat3x2");
842     ASSERT_NE(-1, matLocation);
843 
844     // Set too many float uniforms
845     glUniform1fv(floatLocation, kOverflowSize, &values[0]);
846 
847     // Set too many matrix uniforms, transposed or not
848     glUniformMatrix3x2fv(matLocation, kOverflowSize, GL_FALSE, &values[0]);
849     glUniformMatrix3x2fv(matLocation, kOverflowSize, GL_TRUE, &values[0]);
850 
851     // Same checks but with offsets
852     GLint floatLocationOffset = glGetUniformLocation(mProgram, "uniF[3]");
853     ASSERT_NE(-1, floatLocationOffset);
854     GLint matLocationOffset = glGetUniformLocation(mProgram, "uniMat3x2[3]");
855     ASSERT_NE(-1, matLocationOffset);
856 
857     glUniform1fv(floatLocationOffset, kOverflowSize, &values[0]);
858     glUniformMatrix3x2fv(matLocationOffset, kOverflowSize, GL_FALSE, &values[0]);
859     glUniformMatrix3x2fv(matLocationOffset, kOverflowSize, GL_TRUE, &values[0]);
860 }
861 
862 // Check setting a sampler uniform
TEST_P(UniformTest,Sampler)863 TEST_P(UniformTest, Sampler)
864 {
865     constexpr char kVS[] =
866         "uniform sampler2D tex2D;\n"
867         "void main() {\n"
868         "  gl_Position = vec4(0, 0, 0, 1);\n"
869         "}";
870 
871     constexpr char kFS[] =
872         "precision mediump float;\n"
873         "uniform sampler2D tex2D;\n"
874         "void main() {\n"
875         "  gl_FragColor = texture2D(tex2D, vec2(0, 0));\n"
876         "}";
877 
878     ANGLE_GL_PROGRAM(program, kVS, kFS);
879 
880     GLint location = glGetUniformLocation(program, "tex2D");
881     ASSERT_NE(-1, location);
882 
883     const GLint sampler[] = {0, 0, 0, 0};
884 
885     // before UseProgram
886     glUniform1i(location, sampler[0]);
887     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
888 
889     glUseProgram(program);
890 
891     // Uniform1i
892     glUniform1i(location, sampler[0]);
893     glUniform1iv(location, 1, sampler);
894     EXPECT_GL_NO_ERROR();
895 
896     // Uniform{234}i
897     glUniform2i(location, sampler[0], sampler[0]);
898     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
899     glUniform3i(location, sampler[0], sampler[0], sampler[0]);
900     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
901     glUniform4i(location, sampler[0], sampler[0], sampler[0], sampler[0]);
902     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
903     glUniform2iv(location, 1, sampler);
904     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
905     glUniform3iv(location, 1, sampler);
906     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
907     glUniform4iv(location, 1, sampler);
908     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
909 
910     // Uniform{1234}f
911     const GLfloat f[] = {0, 0, 0, 0};
912     glUniform1f(location, f[0]);
913     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
914     glUniform2f(location, f[0], f[0]);
915     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
916     glUniform3f(location, f[0], f[0], f[0]);
917     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
918     glUniform4f(location, f[0], f[0], f[0], f[0]);
919     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
920     glUniform1fv(location, 1, f);
921     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
922     glUniform2fv(location, 1, f);
923     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
924     glUniform3fv(location, 1, f);
925     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
926     glUniform4fv(location, 1, f);
927     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
928 
929     // < 0 or >= max
930     GLint tooHigh;
931     glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &tooHigh);
932     constexpr GLint tooLow[] = {-1};
933     glUniform1i(location, tooLow[0]);
934     EXPECT_GL_ERROR(GL_INVALID_VALUE);
935     glUniform1iv(location, 1, tooLow);
936     EXPECT_GL_ERROR(GL_INVALID_VALUE);
937     glUniform1i(location, tooHigh);
938     EXPECT_GL_ERROR(GL_INVALID_VALUE);
939     glUniform1iv(location, 1, &tooHigh);
940     EXPECT_GL_ERROR(GL_INVALID_VALUE);
941 }
942 
943 // Check that sampler uniforms only show up one time in the list
TEST_P(UniformTest,SamplerUniformsAppearOnce)944 TEST_P(UniformTest, SamplerUniformsAppearOnce)
945 {
946     int maxVertexTextureImageUnits = 0;
947     glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxVertexTextureImageUnits);
948 
949     // Renderer doesn't support vertex texture fetch, skipping test.
950     ANGLE_SKIP_TEST_IF(!maxVertexTextureImageUnits);
951 
952     constexpr char kVS[] =
953         "attribute vec2 position;\n"
954         "uniform sampler2D tex2D;\n"
955         "varying vec4 color;\n"
956         "void main() {\n"
957         "  gl_Position = vec4(position, 0, 1);\n"
958         "  color = texture2D(tex2D, vec2(0));\n"
959         "}";
960 
961     constexpr char kFS[] =
962         "precision mediump float;\n"
963         "varying vec4 color;\n"
964         "uniform sampler2D tex2D;\n"
965         "void main() {\n"
966         "  gl_FragColor = texture2D(tex2D, vec2(0)) + color;\n"
967         "}";
968 
969     ANGLE_GL_PROGRAM(program, kVS, kFS);
970 
971     GLint activeUniformsCount = 0;
972     glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &activeUniformsCount);
973     ASSERT_EQ(1, activeUniformsCount);
974 
975     GLint size       = 0;
976     GLenum type      = GL_NONE;
977     GLchar name[120] = {0};
978     glGetActiveUniform(program, 0, 100, nullptr, &size, &type, name);
979     EXPECT_EQ(1, size);
980     EXPECT_GLENUM_EQ(GL_SAMPLER_2D, type);
981     EXPECT_STREQ("tex2D", name);
982 
983     EXPECT_GL_NO_ERROR();
984 
985     glDeleteProgram(program);
986 }
987 
988 template <typename T, typename GetUniformV>
CheckOneElement(GetUniformV getUniformv,GLuint program,const std::string & name,int components,T canary)989 void CheckOneElement(GetUniformV getUniformv,
990                      GLuint program,
991                      const std::string &name,
992                      int components,
993                      T canary)
994 {
995     // The buffer getting the results has three chunks
996     //  - A chunk to see underflows
997     //  - A chunk that will hold the result
998     //  - A chunk to see overflows for when components = kChunkSize
999     static const size_t kChunkSize = 4;
1000     std::array<T, 3 * kChunkSize> buffer;
1001     buffer.fill(canary);
1002 
1003     GLint location = glGetUniformLocation(program, name.c_str());
1004     ASSERT_NE(location, -1);
1005 
1006     getUniformv(program, location, &buffer[kChunkSize]);
1007     for (size_t i = 0; i < kChunkSize; i++)
1008     {
1009         ASSERT_EQ(canary, buffer[i]);
1010     }
1011     for (size_t i = kChunkSize + components; i < buffer.size(); i++)
1012     {
1013         ASSERT_EQ(canary, buffer[i]);
1014     }
1015 }
1016 
1017 // Check that getting an element array doesn't return the whole array.
TEST_P(UniformTestES3,ReturnsOnlyOneArrayElement)1018 TEST_P(UniformTestES3, ReturnsOnlyOneArrayElement)
1019 {
1020 
1021     static const size_t kArraySize = 4;
1022     struct UniformArrayInfo
1023     {
1024         UniformArrayInfo(std::string type, std::string name, int components)
1025             : type(type), name(name), components(components)
1026         {}
1027         std::string type;
1028         std::string name;
1029         int components;
1030     };
1031 
1032     // Check for various number of components and types
1033     std::vector<UniformArrayInfo> uniformArrays;
1034     uniformArrays.emplace_back("bool", "uBool", 1);
1035     uniformArrays.emplace_back("vec2", "uFloat", 2);
1036     uniformArrays.emplace_back("ivec3", "uInt", 3);
1037     uniformArrays.emplace_back("uvec4", "uUint", 4);
1038 
1039     std::ostringstream uniformStream;
1040     std::ostringstream additionStream;
1041     for (const auto &array : uniformArrays)
1042     {
1043         uniformStream << "uniform " << array.type << " " << array.name << "["
1044                       << ToString(kArraySize) << "];\n";
1045 
1046         // We need to make use of the uniforms or they get compiled out.
1047         for (int i = 0; i < 4; i++)
1048         {
1049             if (array.components == 1)
1050             {
1051                 additionStream << " + float(" << array.name << "[" << i << "])";
1052             }
1053             else
1054             {
1055                 for (int component = 0; component < array.components; component++)
1056                 {
1057                     additionStream << " + float(" << array.name << "[" << i << "][" << component
1058                                    << "])";
1059                 }
1060             }
1061         }
1062     }
1063 
1064     const std::string vertexShader = "#version 300 es\n" + uniformStream.str() +
1065                                      "void main()\n"
1066                                      "{\n"
1067                                      "    gl_Position = vec4(1.0" +
1068                                      additionStream.str() +
1069                                      ");\n"
1070                                      "}";
1071 
1072     constexpr char kFS[] =
1073         "#version 300 es\n"
1074         "precision mediump float;\n"
1075         "out vec4 color;\n"
1076         "void main ()\n"
1077         "{\n"
1078         "    color = vec4(1, 0, 0, 1);\n"
1079         "}";
1080 
1081     mProgram = CompileProgram(vertexShader.c_str(), kFS);
1082     ASSERT_NE(0u, mProgram);
1083 
1084     glUseProgram(mProgram);
1085 
1086     for (const auto &uniformArray : uniformArrays)
1087     {
1088         for (size_t index = 0; index < kArraySize; index++)
1089         {
1090             std::string strIndex = "[" + ToString(index) + "]";
1091             // Check all the different glGetUniformv functions
1092             CheckOneElement<float>(glGetUniformfv, mProgram, uniformArray.name + strIndex,
1093                                    uniformArray.components, 42.4242f);
1094             CheckOneElement<int>(glGetUniformiv, mProgram, uniformArray.name + strIndex,
1095                                  uniformArray.components, 0x7BADBED5);
1096             CheckOneElement<unsigned int>(glGetUniformuiv, mProgram, uniformArray.name + strIndex,
1097                                           uniformArray.components, 0xDEADBEEF);
1098         }
1099     }
1100 }
1101 
1102 // This test reproduces a regression when Intel windows driver upgrades to 4944. In some situation,
1103 // when a boolean uniform with false value is used as the if and for condtions, the bug will be
1104 // triggered. It seems that the shader doesn't get a right 'false' value from the uniform.
TEST_P(UniformTestES3,BooleanUniformAsIfAndForCondition)1105 TEST_P(UniformTestES3, BooleanUniformAsIfAndForCondition)
1106 {
1107     const char kFragShader[] =
1108         R"(#version 300 es
1109         precision mediump float;
1110         uniform bool u;
1111         out vec4 result;
1112         int sideEffectCounter;
1113 
1114         bool foo() {
1115           ++sideEffectCounter;
1116           return true;
1117         }
1118 
1119         void main() {
1120           sideEffectCounter = 0;
1121           bool condition = u;
1122           if (condition)
1123           {
1124             condition = foo();
1125           }
1126           for(int iterations = 0; condition;) {
1127             ++iterations;
1128             if (iterations >= 10) {
1129               break;
1130             }
1131 
1132             if (condition)
1133             {
1134               condition = foo();
1135             }
1136           }
1137 
1138           bool success = (!u && sideEffectCounter == 0);
1139           result = (success) ? vec4(0, 1.0, 0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);
1140         })";
1141 
1142     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFragShader);
1143 
1144     glUseProgram(program);
1145 
1146     GLint uniformLocation = glGetUniformLocation(program, "u");
1147     ASSERT_NE(uniformLocation, -1);
1148 
1149     glUniform1i(uniformLocation, GL_FALSE);
1150 
1151     drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f);
1152     ASSERT_GL_NO_ERROR();
1153     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1154 }
1155 
1156 class UniformTestES31 : public ANGLETest<>
1157 {
1158   protected:
UniformTestES31()1159     UniformTestES31() : mProgram(0) {}
1160 
testTearDown()1161     void testTearDown() override
1162     {
1163         if (mProgram != 0)
1164         {
1165             glDeleteProgram(mProgram);
1166             mProgram = 0;
1167         }
1168     }
1169 
1170     GLuint mProgram;
1171 };
1172 
1173 // Test that uniform locations get set correctly for structure members.
1174 // ESSL 3.10.4 section 4.4.3.
TEST_P(UniformTestES31,StructLocationLayoutQualifier)1175 TEST_P(UniformTestES31, StructLocationLayoutQualifier)
1176 {
1177     constexpr char kFS[] =
1178         "#version 310 es\n"
1179         "out highp vec4 my_FragColor;\n"
1180         "struct S\n"
1181         "{\n"
1182         "    highp float f;\n"
1183         "    highp float f2;\n"
1184         "};\n"
1185         "uniform layout(location=12) S uS;\n"
1186         "void main()\n"
1187         "{\n"
1188         "    my_FragColor = vec4(uS.f, uS.f2, 0, 1);\n"
1189         "}";
1190 
1191     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Zero(), kFS);
1192 
1193     EXPECT_EQ(12, glGetUniformLocation(program, "uS.f"));
1194     EXPECT_EQ(13, glGetUniformLocation(program, "uS.f2"));
1195 }
1196 
1197 // Set uniform location with a layout qualifier in the fragment shader. The same uniform exists in
1198 // the vertex shader, but doesn't have a location specified there.
TEST_P(UniformTestES31,UniformLocationInFragmentShader)1199 TEST_P(UniformTestES31, UniformLocationInFragmentShader)
1200 {
1201     constexpr char kVS[] =
1202         "#version 310 es\n"
1203         "uniform highp sampler2D tex2D;\n"
1204         "void main()\n"
1205         "{\n"
1206         "    gl_Position = texture(tex2D, vec2(0));\n"
1207         "}";
1208 
1209     constexpr char kFS[] =
1210         "#version 310 es\n"
1211         "precision mediump float;\n"
1212         "out vec4 my_FragColor;\n"
1213         "uniform layout(location=12) highp sampler2D tex2D;\n"
1214         "void main()\n"
1215         "{\n"
1216         "    my_FragColor = texture(tex2D, vec2(0));\n"
1217         "}";
1218 
1219     ANGLE_GL_PROGRAM(program, kVS, kFS);
1220 
1221     EXPECT_EQ(12, glGetUniformLocation(program, "tex2D"));
1222 }
1223 
1224 // Test two unused uniforms that have the same location.
1225 // ESSL 3.10.4 section 4.4.3: "No two default-block uniform variables in the program can have the
1226 // same location, even if they are unused, otherwise a compiler or linker error will be generated."
TEST_P(UniformTestES31,UnusedUniformsConflictingLocation)1227 TEST_P(UniformTestES31, UnusedUniformsConflictingLocation)
1228 {
1229     constexpr char kVS[] =
1230         "#version 310 es\n"
1231         "uniform layout(location=12) highp sampler2D texA;\n"
1232         "void main()\n"
1233         "{\n"
1234         "    gl_Position = vec4(0);\n"
1235         "}";
1236 
1237     constexpr char kFS[] =
1238         "#version 310 es\n"
1239         "out highp vec4 my_FragColor;\n"
1240         "uniform layout(location=12) highp sampler2D texB;\n"
1241         "void main()\n"
1242         "{\n"
1243         "    my_FragColor = vec4(0);\n"
1244         "}";
1245 
1246     mProgram = CompileProgram(kVS, kFS);
1247     EXPECT_EQ(0u, mProgram);
1248 }
1249 
1250 // Test two unused uniforms that have overlapping locations once all array elements are taken into
1251 // account.
1252 // ESSL 3.10.4 section 4.4.3: "No two default-block uniform variables in the program can have the
1253 // same location, even if they are unused, otherwise a compiler or linker error will be generated."
TEST_P(UniformTestES31,UnusedUniformArraysConflictingLocation)1254 TEST_P(UniformTestES31, UnusedUniformArraysConflictingLocation)
1255 {
1256     constexpr char kVS[] =
1257         "#version 310 es\n"
1258         "uniform layout(location=11) highp vec4 uA[2];\n"
1259         "void main()\n"
1260         "{\n"
1261         "    gl_Position = vec4(0);\n"
1262         "}";
1263 
1264     constexpr char kFS[] =
1265         "#version 310 es\n"
1266         "out highp vec4 my_FragColor;\n"
1267         "uniform layout(location=12) highp vec4 uB;\n"
1268         "void main()\n"
1269         "{\n"
1270         "    my_FragColor = vec4(0);\n"
1271         "}";
1272 
1273     mProgram = CompileProgram(kVS, kFS);
1274     EXPECT_EQ(0u, mProgram);
1275 }
1276 
1277 // Test a uniform struct containing a non-square matrix and a boolean.
1278 // Minimal test case for a bug revealed by dEQP tests.
TEST_P(UniformTestES3,StructWithNonSquareMatrixAndBool)1279 TEST_P(UniformTestES3, StructWithNonSquareMatrixAndBool)
1280 {
1281     constexpr char kFS[] =
1282         "#version 300 es\n"
1283         "precision highp float;\n"
1284         "out highp vec4 my_color;\n"
1285         "struct S\n"
1286         "{\n"
1287         "    mat2x4 m;\n"
1288         "    bool b;\n"
1289         "};\n"
1290         "uniform S uni;\n"
1291         "void main()\n"
1292         "{\n"
1293         "    my_color = vec4(1.0);\n"
1294         "    if (!uni.b) { my_color.g = 0.0; }"
1295         "}\n";
1296 
1297     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
1298 
1299     glUseProgram(program);
1300 
1301     GLint location = glGetUniformLocation(program, "uni.b");
1302     ASSERT_NE(-1, location);
1303     glUniform1i(location, 1);
1304 
1305     drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f);
1306 
1307     ASSERT_GL_NO_ERROR();
1308     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
1309 }
1310 
1311 // Test that matrix uniform upload is correct.
TEST_P(UniformTestES3,MatrixUniformUpload)1312 TEST_P(UniformTestES3, MatrixUniformUpload)
1313 {
1314     constexpr size_t kMinDims = 2;
1315     constexpr size_t kMaxDims = 4;
1316 
1317     GLfloat matrixValues[kMaxDims * kMaxDims];
1318 
1319     for (size_t i = 0; i < kMaxDims * kMaxDims; ++i)
1320     {
1321         matrixValues[i] = static_cast<GLfloat>(i);
1322     }
1323 
1324     using UniformMatrixCxRfv = decltype(glUniformMatrix2fv);
1325     UniformMatrixCxRfv uniformMatrixCxRfv[kMaxDims + 1][kMaxDims + 1] = {
1326         {nullptr, nullptr, nullptr, nullptr, nullptr},
1327         {nullptr, nullptr, nullptr, nullptr, nullptr},
1328         {nullptr, nullptr, glUniformMatrix2fv, glUniformMatrix2x3fv, glUniformMatrix2x4fv},
1329         {nullptr, nullptr, glUniformMatrix3x2fv, glUniformMatrix3fv, glUniformMatrix3x4fv},
1330         {nullptr, nullptr, glUniformMatrix4x2fv, glUniformMatrix4x3fv, glUniformMatrix4fv},
1331     };
1332 
1333     for (int transpose = 0; transpose < 2; ++transpose)
1334     {
1335         for (size_t cols = kMinDims; cols <= kMaxDims; ++cols)
1336         {
1337             for (size_t rows = kMinDims; rows <= kMaxDims; ++rows)
1338             {
1339                 std::ostringstream shader;
1340                 shader << "#version 300 es\n"
1341                           "precision highp float;\n"
1342                           "out highp vec4 colorOut;\n"
1343                           "uniform mat"
1344                        << cols << 'x' << rows
1345                        << " unused;\n"
1346                           "uniform mat"
1347                        << cols << 'x' << rows
1348                        << " m;\n"
1349                           "void main()\n"
1350                           "{\n"
1351                           "  bool isCorrect =";
1352 
1353                 for (size_t col = 0; col < cols; ++col)
1354                 {
1355                     for (size_t row = 0; row < rows; ++row)
1356                     {
1357                         size_t value;
1358                         if (!transpose)
1359                         {
1360                             // Matrix data is uploaded column-major.
1361                             value = col * rows + row;
1362                         }
1363                         else
1364                         {
1365                             // Matrix data is uploaded row-major.
1366                             value = row * cols + col;
1367                         }
1368 
1369                         if (value != 0)
1370                         {
1371                             shader << "&&\n    ";
1372                         }
1373 
1374                         shader << "(m[" << col << "][" << row << "] == " << value << ".0)";
1375                     }
1376                 }
1377 
1378                 shader << ";\n  colorOut = vec4(isCorrect);\n"
1379                           "}\n";
1380 
1381                 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), shader.str().c_str());
1382 
1383                 glUseProgram(program);
1384 
1385                 GLint location = glGetUniformLocation(program, "m");
1386                 ASSERT_NE(-1, location);
1387 
1388                 uniformMatrixCxRfv[cols][rows](location, 1, transpose != 0, matrixValues);
1389                 ASSERT_GL_NO_ERROR();
1390 
1391                 drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f);
1392 
1393                 ASSERT_GL_NO_ERROR();
1394                 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white)
1395                     << " transpose = " << transpose << ", cols = " << cols << ", rows = " << rows;
1396             }
1397         }
1398     }
1399 }
1400 
1401 // Test that uniforms with reserved OpenGL names that aren't reserved in GL ES 2 work correctly.
TEST_P(UniformTest,UniformWithReservedOpenGLName)1402 TEST_P(UniformTest, UniformWithReservedOpenGLName)
1403 {
1404     constexpr char kFS[] =
1405         "precision mediump float;\n"
1406         "uniform float buffer;"
1407         "void main() {\n"
1408         "    gl_FragColor = vec4(buffer);\n"
1409         "}";
1410 
1411     mProgram = CompileProgram(essl1_shaders::vs::Simple(), kFS);
1412     ASSERT_NE(mProgram, 0u);
1413 
1414     GLint location = glGetUniformLocation(mProgram, "buffer");
1415     ASSERT_NE(-1, location);
1416 
1417     glUseProgram(mProgram);
1418     glUniform1f(location, 1.0f);
1419 
1420     drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.0f);
1421 
1422     ASSERT_GL_NO_ERROR();
1423     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
1424 }
1425 
1426 // Test that unused sampler array elements do not corrupt used sampler array elements. Checks for a
1427 // bug where unused samplers in an array would mark the whole array unused.
TEST_P(UniformTest,UnusedUniformsInSamplerArray)1428 TEST_P(UniformTest, UnusedUniformsInSamplerArray)
1429 {
1430     constexpr char kVS[] = R"(precision highp float;
1431 attribute vec4 position;
1432 varying vec2 texcoord;
1433 void main()
1434 {
1435     gl_Position = position;
1436     texcoord = (position.xy * 0.5) + 0.5;
1437 })";
1438     constexpr char kFS[] = R"(precision highp float;
1439 uniform sampler2D tex[3];
1440 varying vec2 texcoord;
1441 void main()
1442 {
1443     gl_FragColor = texture2D(tex[0], texcoord);
1444 })";
1445 
1446     mProgram = CompileProgram(kVS, kFS);
1447 
1448     ASSERT_NE(mProgram, 0u);
1449     GLint texLocation = glGetUniformLocation(mProgram, "tex[0]");
1450     ASSERT_NE(-1, texLocation);
1451     glUseProgram(mProgram);
1452     glUniform1i(texLocation, 0);
1453     GLTexture tex;
1454     glActiveTexture(GL_TEXTURE0);
1455     glBindTexture(GL_TEXTURE_2D, tex);
1456     constexpr GLsizei kTextureSize = 2;
1457     std::vector<GLColor> textureData(kTextureSize * kTextureSize, GLColor::green);
1458     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTextureSize, kTextureSize, 0, GL_RGBA,
1459                  GL_UNSIGNED_BYTE, textureData.data());
1460     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1461     drawQuad(mProgram, "position", 0.5f);
1462     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1463 }
1464 
TEST_P(UniformTest,UnusedStructInlineUniform)1465 TEST_P(UniformTest, UnusedStructInlineUniform)
1466 {
1467     constexpr char kVS[] = R"(precision highp float;
1468 attribute vec4 position;
1469 void main()
1470 {
1471     gl_Position = position;
1472 })";
1473 
1474     constexpr char kFS[] = R"(precision highp float;
1475 uniform struct {
1476   vec3  aVec3;
1477   vec2 aVec2;
1478 }aUniform;
1479 varying vec2 texcoord;
1480 void main()
1481 {
1482     gl_FragColor = vec4(0,1,0,1);
1483 })";
1484 
1485     mProgram = CompileProgram(kVS, kFS);
1486     ASSERT_NE(mProgram, 0u);
1487     drawQuad(mProgram, "position", 0.5f);
1488     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1489 }
1490 
TEST_P(UniformTest,UnusedStructInlineUniformWithSampler)1491 TEST_P(UniformTest, UnusedStructInlineUniformWithSampler)
1492 {
1493     constexpr char kVS[] = R"(precision highp float;
1494 attribute vec4 position;
1495 void main()
1496 {
1497     gl_Position = position;
1498 })";
1499 
1500     constexpr char kFS[] = R"(precision highp float;
1501 uniform struct {
1502   sampler2D  aSampler;
1503   vec3 aVec3;
1504 }aUniform;
1505 varying vec2 texcoord;
1506 void main()
1507 {
1508     gl_FragColor = vec4(0,1,0,1);
1509 })";
1510 
1511     mProgram = CompileProgram(kVS, kFS);
1512     ASSERT_NE(mProgram, 0u);
1513     drawQuad(mProgram, "position", 0.5f);
1514     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1515 }
1516 
1517 // Bug: chromium:4210448 : Ensure programs properly
1518 // compiles and renders where the uniforms form
1519 // a struct with an alignment not matched with
1520 // the actual size of the individual members.
1521 // (Metal)
TEST_P(UniformTest,Vec4Vec2SizeAlignment)1522 TEST_P(UniformTest, Vec4Vec2SizeAlignment)
1523 {
1524     constexpr char kVS[] = R"(precision highp float;
1525 attribute vec4 position;
1526 uniform vec4 uniformA;
1527 uniform vec4 uniformB;
1528 uniform vec2 uniformC;
1529 void main()
1530 {
1531     gl_Position = position+uniformA +
1532     uniformB + vec4(uniformC.x, uniformC.y, 0, 0);
1533 })";
1534     constexpr char kFS[] = R"(precision highp float;
1535 void main()
1536 {
1537     gl_FragColor = vec4(0,1,0,1);
1538 })";
1539     mProgram             = CompileProgram(kVS, kFS);
1540     ASSERT_NE(mProgram, 0u);
1541     drawQuad(mProgram, "position", 0.5f);
1542     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1543 }
1544 
1545 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
1546 // tests should be run against.
1547 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(SimpleUniformTest);
1548 
1549 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(UniformTest);
1550 
1551 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UniformTestES3);
1552 ANGLE_INSTANTIATE_TEST_ES3(UniformTestES3);
1553 
1554 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UniformTestES31);
1555 ANGLE_INSTANTIATE_TEST_ES31(UniformTestES31);
1556 
1557 }  // namespace
1558