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