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