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