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