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