xref: /aosp_15_r20/external/angle/src/tests/gl_tests/UniformBufferTest.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 #include "test_utils/gl_raii.h"
9 #include "util/random_utils.h"
10 
11 using namespace angle;
12 
13 namespace
14 {
15 
16 class UniformBufferTest : public ANGLETest<>
17 {
18   protected:
UniformBufferTest()19     UniformBufferTest()
20     {
21         setWindowWidth(128);
22         setWindowHeight(128);
23         setConfigRedBits(8);
24         setConfigGreenBits(8);
25         setConfigBlueBits(8);
26         setConfigAlphaBits(8);
27     }
28 
testSetUp()29     void testSetUp() override
30     {
31         mkFS = R"(#version 300 es
32 precision highp float;
33 uniform uni { vec4 color; };
34 out vec4 fragColor;
35 void main()
36 {
37     fragColor = color;
38 })";
39 
40         mProgram = CompileProgram(essl3_shaders::vs::Simple(), mkFS);
41         ASSERT_NE(mProgram, 0u);
42 
43         mUniformBufferIndex = glGetUniformBlockIndex(mProgram, "uni");
44         ASSERT_NE(mUniformBufferIndex, -1);
45 
46         glGenBuffers(1, &mUniformBuffer);
47 
48         ASSERT_GL_NO_ERROR();
49     }
50 
testTearDown()51     void testTearDown() override
52     {
53         glDeleteBuffers(1, &mUniformBuffer);
54         glDeleteProgram(mProgram);
55     }
56 
57     const char *mkFS;
58     GLuint mProgram;
59     GLint mUniformBufferIndex;
60     GLuint mUniformBuffer;
61 };
62 
63 // Basic UBO functionality.
TEST_P(UniformBufferTest,Simple)64 TEST_P(UniformBufferTest, Simple)
65 {
66     glClear(GL_COLOR_BUFFER_BIT);
67     float floatData[4] = {0.5f, 0.75f, 0.25f, 1.0f};
68 
69     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
70     glBufferData(GL_UNIFORM_BUFFER, sizeof(float) * 4, floatData, GL_STATIC_DRAW);
71 
72     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
73 
74     glUniformBlockBinding(mProgram, mUniformBufferIndex, 0);
75     drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
76 
77     ASSERT_GL_NO_ERROR();
78     EXPECT_PIXEL_NEAR(0, 0, 128, 191, 64, 255, 1);
79 }
80 
81 // Test a scenario that draws then update UBO (using bufferData or bufferSubData or mapBuffer) then
82 // draws with updated data.
TEST_P(UniformBufferTest,DrawThenUpdateThenDraw)83 TEST_P(UniformBufferTest, DrawThenUpdateThenDraw)
84 {
85     constexpr char kVS[] = R"(#version 300 es
86 precision highp float;
87 
88 void main()
89 {
90     vec2 position = vec2(float(gl_VertexID >> 1), float(gl_VertexID & 1));
91     position = 2.0 * position - 1.0;
92     gl_Position = vec4(position.x, position.y, 0.0, 1.0);
93 })";
94 
95     enum class BufferUpdateMethod
96     {
97         BUFFER_DATA,
98         BUFFER_SUB_DATA,
99         MAP_BUFFER,
100     };
101 
102     ANGLE_GL_PROGRAM(program, kVS, mkFS);
103     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "uni");
104     ASSERT_NE(uniformBufferIndex, -1);
105 
106     for (BufferUpdateMethod method :
107          {BufferUpdateMethod::BUFFER_DATA, BufferUpdateMethod::BUFFER_SUB_DATA,
108           BufferUpdateMethod::MAP_BUFFER})
109     {
110         glClear(GL_COLOR_BUFFER_BIT);
111         float floatData1[4] = {0.25f, 0.75f, 0.125f, 1.0f};
112 
113         GLBuffer uniformBuffer;
114         glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer);
115         glBufferData(GL_UNIFORM_BUFFER, sizeof(float) * 4, floatData1, GL_DYNAMIC_DRAW);
116 
117         glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer);
118 
119         glEnable(GL_BLEND);
120         glBlendFunc(GL_ONE, GL_ONE);
121 
122         glUniformBlockBinding(program, uniformBufferIndex, 0);
123         glUseProgram(program);
124         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
125 
126         float floatData2[4] = {0.25f, 0.0f, 0.125f, 0.0f};
127         switch (method)
128         {
129             case BufferUpdateMethod::BUFFER_DATA:
130                 glBufferData(GL_UNIFORM_BUFFER, sizeof(float) * 4, floatData2, GL_DYNAMIC_DRAW);
131                 break;
132             case BufferUpdateMethod::BUFFER_SUB_DATA:
133                 glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(float) * 4, floatData2);
134                 break;
135             case BufferUpdateMethod::MAP_BUFFER:
136                 void *mappedBuffer =
137                     glMapBufferRange(GL_UNIFORM_BUFFER, 0, sizeof(float) * 4, GL_MAP_WRITE_BIT);
138                 memcpy(mappedBuffer, floatData2, sizeof(floatData2));
139                 glUnmapBuffer(GL_UNIFORM_BUFFER);
140                 break;
141         }
142         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
143 
144         ASSERT_GL_NO_ERROR();
145         EXPECT_PIXEL_NEAR(0, 0, 128, 191, 64, 255, 1);
146     }
147 }
148 
149 // Test that using a UBO with a non-zero offset and size actually works.
150 // The first step of this test renders a color from a UBO with a zero offset.
151 // The second step renders a color from a UBO with a non-zero offset.
TEST_P(UniformBufferTest,UniformBufferRange)152 TEST_P(UniformBufferTest, UniformBufferRange)
153 {
154     int px = getWindowWidth() / 2;
155     int py = getWindowHeight() / 2;
156 
157     // Query the uniform buffer alignment requirement
158     GLint alignment;
159     glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &alignment);
160 
161     GLint64 maxUniformBlockSize;
162     glGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize);
163     if (alignment >= maxUniformBlockSize)
164     {
165         // ANGLE doesn't implement UBO offsets for this platform.
166         // Ignore the test case.
167         return;
168     }
169 
170     ASSERT_GL_NO_ERROR();
171 
172     // Let's create a buffer which contains two vec4.
173     GLuint vec4Size = 4 * sizeof(float);
174     GLuint stride   = 0;
175     do
176     {
177         stride += alignment;
178     } while (stride < vec4Size);
179 
180     std::vector<char> v(2 * stride);
181     float *first  = reinterpret_cast<float *>(v.data());
182     float *second = reinterpret_cast<float *>(v.data() + stride);
183 
184     first[0] = 10.f / 255.f;
185     first[1] = 20.f / 255.f;
186     first[2] = 30.f / 255.f;
187     first[3] = 40.f / 255.f;
188 
189     second[0] = 110.f / 255.f;
190     second[1] = 120.f / 255.f;
191     second[2] = 130.f / 255.f;
192     second[3] = 140.f / 255.f;
193 
194     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
195     // We use on purpose a size which is not a multiple of the alignment.
196     glBufferData(GL_UNIFORM_BUFFER, stride + vec4Size, v.data(), GL_STATIC_DRAW);
197 
198     glUniformBlockBinding(mProgram, mUniformBufferIndex, 0);
199 
200     EXPECT_GL_NO_ERROR();
201 
202     // Bind the first part of the uniform buffer and draw
203     // Use a size which is smaller than the alignment to check
204     // to check that this case is handle correctly in the conversion to 11.1.
205     glBindBufferRange(GL_UNIFORM_BUFFER, 0, mUniformBuffer, 0, vec4Size);
206     drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
207     EXPECT_GL_NO_ERROR();
208     EXPECT_PIXEL_EQ(px, py, 10, 20, 30, 40);
209 
210     // Bind the second part of the uniform buffer and draw
211     // Furthermore the D3D11.1 backend will internally round the vec4Size (16 bytes) to a stride
212     // (256 bytes) hence it will try to map the range [stride, 2 * stride] which is out-of-bound of
213     // the buffer bufferSize = stride + vec4Size < 2 * stride. Ensure that this behaviour works.
214     glBindBufferRange(GL_UNIFORM_BUFFER, 0, mUniformBuffer, stride, vec4Size);
215     drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
216     EXPECT_GL_NO_ERROR();
217     EXPECT_PIXEL_EQ(px, py, 110, 120, 130, 140);
218 }
219 
220 // Test uniform block bindings.
TEST_P(UniformBufferTest,UniformBufferBindings)221 TEST_P(UniformBufferTest, UniformBufferBindings)
222 {
223     int px = getWindowWidth() / 2;
224     int py = getWindowHeight() / 2;
225 
226     ASSERT_GL_NO_ERROR();
227 
228     // Let's create a buffer which contains one vec4.
229     GLuint vec4Size = 4 * sizeof(float);
230     std::vector<char> v(vec4Size);
231     float *first = reinterpret_cast<float *>(v.data());
232 
233     first[0] = 10.f / 255.f;
234     first[1] = 20.f / 255.f;
235     first[2] = 30.f / 255.f;
236     first[3] = 40.f / 255.f;
237 
238     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
239     glBufferData(GL_UNIFORM_BUFFER, vec4Size, v.data(), GL_STATIC_DRAW);
240 
241     EXPECT_GL_NO_ERROR();
242 
243     // Try to bind the buffer to binding point 2
244     glUniformBlockBinding(mProgram, mUniformBufferIndex, 2);
245     glBindBufferBase(GL_UNIFORM_BUFFER, 2, mUniformBuffer);
246     drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
247     EXPECT_GL_NO_ERROR();
248     EXPECT_PIXEL_EQ(px, py, 10, 20, 30, 40);
249 
250     // Clear the framebuffer
251     glClearColor(0.0, 0.0, 0.0, 0.0);
252     glClear(GL_COLOR_BUFFER_BIT);
253     EXPECT_PIXEL_EQ(px, py, 0, 0, 0, 0);
254 
255     // Try to bind the buffer to another binding point
256     glUniformBlockBinding(mProgram, mUniformBufferIndex, 5);
257     glBindBufferBase(GL_UNIFORM_BUFFER, 5, mUniformBuffer);
258     drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
259     EXPECT_GL_NO_ERROR();
260     EXPECT_PIXEL_EQ(px, py, 10, 20, 30, 40);
261 }
262 
263 // Test when the only change between draw calls is the change in the uniform binding range.
TEST_P(UniformBufferTest,BufferBindingRangeChange)264 TEST_P(UniformBufferTest, BufferBindingRangeChange)
265 {
266     constexpr GLsizei kVec4Size = 4 * sizeof(float);
267 
268     GLint alignment;
269     glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &alignment);
270     if (alignment < kVec4Size)
271     {
272         alignment = kVec4Size;
273     }
274     ASSERT_EQ(alignment % 4, 0);
275 
276     // Put two colors in the uniform buffer, the sum of which is yellow.
277     // Note: |alignment| is in bytes, so we can place each uniform in |alignment/4| floats.
278     std::vector<float> colors(alignment / 2);
279     // Half red
280     colors[0] = 0.55;
281     colors[1] = 0.0;
282     colors[2] = 0.0;
283     colors[3] = 0.35;
284     // Greenish yellow
285     colors[alignment / 4 + 0] = 0.55;
286     colors[alignment / 4 + 1] = 1.0;
287     colors[alignment / 4 + 2] = 0.0;
288     colors[alignment / 4 + 3] = 0.75;
289 
290     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
291     glBufferData(GL_UNIFORM_BUFFER, alignment * 2, colors.data(), GL_STATIC_DRAW);
292 
293     const GLint positionLoc = glGetAttribLocation(mProgram, essl3_shaders::PositionAttrib());
294     setupQuadVertexBuffer(0.5f, 1.0f);
295     glEnableVertexAttribArray(positionLoc);
296     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
297 
298     // Enable blending
299     glEnable(GL_BLEND);
300     glBlendFunc(GL_ONE, GL_ONE);
301 
302     glClearColor(0, 0, 0, 0);
303     glClear(GL_COLOR_BUFFER_BIT);
304 
305     // Draw twice, binding the uniform buffer to a different range each time
306     glUseProgram(mProgram);
307     glBindBufferRange(GL_UNIFORM_BUFFER, 0, mUniformBuffer, 0, kVec4Size);
308     glDrawArrays(GL_TRIANGLES, 0, 6);
309     glBindBufferRange(GL_UNIFORM_BUFFER, 0, mUniformBuffer, alignment, kVec4Size);
310     glDrawArrays(GL_TRIANGLES, 0, 6);
311     EXPECT_GL_NO_ERROR();
312 
313     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::yellow);
314 }
315 
316 // Test when glUniformBlockBinding is called between draws while the program is not current.
317 // Regression test for a missing dirty bit bug in this scenario.
TEST_P(UniformBufferTest,BufferBlockBindingChange)318 TEST_P(UniformBufferTest, BufferBlockBindingChange)
319 {
320     constexpr GLsizei kVec4Size = 4 * sizeof(float);
321 
322     GLint alignment;
323     glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &alignment);
324     if (alignment < kVec4Size)
325     {
326         alignment = kVec4Size;
327     }
328     ASSERT_EQ(alignment % 4, 0);
329 
330     // Put two colors in the uniform buffer, the sum of which is yellow.
331     // Note: |alignment| is in bytes, so we can place each uniform in |alignment/4| floats.
332     std::vector<float> colors(alignment / 2);
333     // Half red
334     colors[0] = 0.55;
335     colors[1] = 0.0;
336     colors[2] = 0.0;
337     colors[3] = 0.35;
338     // Greenish yellow
339     colors[alignment / 4 + 0] = 0.55;
340     colors[alignment / 4 + 1] = 1.0;
341     colors[alignment / 4 + 2] = 0.0;
342     colors[alignment / 4 + 3] = 0.75;
343 
344     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
345     glBufferData(GL_UNIFORM_BUFFER, alignment * 2, colors.data(), GL_STATIC_DRAW);
346 
347     const GLint positionLoc = glGetAttribLocation(mProgram, essl3_shaders::PositionAttrib());
348     setupQuadVertexBuffer(0.5f, 1.0f);
349     glEnableVertexAttribArray(positionLoc);
350     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
351 
352     // Enable blending
353     glEnable(GL_BLEND);
354     glBlendFunc(GL_ONE, GL_ONE);
355 
356     glClearColor(0, 0, 0, 0);
357     glClear(GL_COLOR_BUFFER_BIT);
358 
359     // Draw twice, binding the uniform buffer to a different range each time
360     glUseProgram(mProgram);
361     glBindBufferRange(GL_UNIFORM_BUFFER, 0, mUniformBuffer, 0, kVec4Size);
362     glDrawArrays(GL_TRIANGLES, 0, 6);
363 
364     // Change the block binding while the program is not current
365     glUseProgram(0);
366     glUniformBlockBinding(mProgram, 0, 1);
367     glUseProgram(mProgram);
368 
369     glBindBufferRange(GL_UNIFORM_BUFFER, 1, mUniformBuffer, alignment, kVec4Size);
370     glDrawArrays(GL_TRIANGLES, 0, 6);
371     EXPECT_GL_NO_ERROR();
372 
373     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::yellow);
374 }
375 
376 // Update a UBO many time and verify that ANGLE uses the latest version of the data.
377 // https://code.google.com/p/angleproject/issues/detail?id=965
TEST_P(UniformBufferTest,UniformBufferManyUpdates)378 TEST_P(UniformBufferTest, UniformBufferManyUpdates)
379 {
380     // TODO(jmadill): Figure out why this fails on OSX Intel OpenGL.
381     ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL());
382 
383     int px = getWindowWidth() / 2;
384     int py = getWindowHeight() / 2;
385 
386     ASSERT_GL_NO_ERROR();
387 
388     float data[4];
389 
390     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
391     glBufferData(GL_UNIFORM_BUFFER, sizeof(data), nullptr, GL_DYNAMIC_DRAW);
392     glUniformBlockBinding(mProgram, mUniformBufferIndex, 0);
393     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
394 
395     EXPECT_GL_NO_ERROR();
396 
397     // Repeteadly update the data and draw
398     for (size_t i = 0; i < 10; ++i)
399     {
400         data[0] = (i + 10.f) / 255.f;
401         data[1] = (i + 20.f) / 255.f;
402         data[2] = (i + 30.f) / 255.f;
403         data[3] = (i + 40.f) / 255.f;
404 
405         glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(data), data);
406 
407         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
408         EXPECT_GL_NO_ERROR();
409         EXPECT_PIXEL_EQ(px, py, i + 10, i + 20, i + 30, i + 40);
410     }
411 }
412 
413 // Use a large number of buffer ranges (compared to the actual size of the UBO)
TEST_P(UniformBufferTest,ManyUniformBufferRange)414 TEST_P(UniformBufferTest, ManyUniformBufferRange)
415 {
416     int px = getWindowWidth() / 2;
417     int py = getWindowHeight() / 2;
418 
419     // Query the uniform buffer alignment requirement
420     GLint alignment;
421     glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &alignment);
422 
423     GLint64 maxUniformBlockSize;
424     glGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize);
425     if (alignment >= maxUniformBlockSize)
426     {
427         // ANGLE doesn't implement UBO offsets for this platform.
428         // Ignore the test case.
429         return;
430     }
431 
432     ASSERT_GL_NO_ERROR();
433 
434     // Let's create a buffer which contains eight vec4.
435     GLuint vec4Size = 4 * sizeof(float);
436     GLuint stride   = 0;
437     do
438     {
439         stride += alignment;
440     } while (stride < vec4Size);
441 
442     std::vector<char> v(8 * stride);
443 
444     for (size_t i = 0; i < 8; ++i)
445     {
446         float *data = reinterpret_cast<float *>(v.data() + i * stride);
447 
448         data[0] = (i + 10.f) / 255.f;
449         data[1] = (i + 20.f) / 255.f;
450         data[2] = (i + 30.f) / 255.f;
451         data[3] = (i + 40.f) / 255.f;
452     }
453 
454     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
455     glBufferData(GL_UNIFORM_BUFFER, v.size(), v.data(), GL_STATIC_DRAW);
456 
457     glUniformBlockBinding(mProgram, mUniformBufferIndex, 0);
458 
459     EXPECT_GL_NO_ERROR();
460 
461     // Bind each possible offset
462     for (size_t i = 0; i < 8; ++i)
463     {
464         glBindBufferRange(GL_UNIFORM_BUFFER, 0, mUniformBuffer, i * stride, stride);
465         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
466         EXPECT_GL_NO_ERROR();
467         EXPECT_PIXEL_EQ(px, py, 10 + i, 20 + i, 30 + i, 40 + i);
468     }
469 
470     // Try to bind larger range
471     for (size_t i = 0; i < 7; ++i)
472     {
473         glBindBufferRange(GL_UNIFORM_BUFFER, 0, mUniformBuffer, i * stride, 2 * stride);
474         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
475         EXPECT_GL_NO_ERROR();
476         EXPECT_PIXEL_EQ(px, py, 10 + i, 20 + i, 30 + i, 40 + i);
477     }
478 
479     // Try to bind even larger range
480     for (size_t i = 0; i < 5; ++i)
481     {
482         glBindBufferRange(GL_UNIFORM_BUFFER, 0, mUniformBuffer, i * stride, 4 * stride);
483         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
484         EXPECT_GL_NO_ERROR();
485         EXPECT_PIXEL_EQ(px, py, 10 + i, 20 + i, 30 + i, 40 + i);
486     }
487 }
488 
489 // Tests that active uniforms have the right names.
TEST_P(UniformBufferTest,ActiveUniformNames)490 TEST_P(UniformBufferTest, ActiveUniformNames)
491 {
492     constexpr char kVS[] =
493         "#version 300 es\n"
494         "in vec2 position;\n"
495         "out vec2 v;\n"
496         "uniform blockName1 {\n"
497         "  float f1;\n"
498         "} instanceName1;\n"
499         "uniform blockName2 {\n"
500         "  float f2;\n"
501         "} instanceName2[1];\n"
502         "void main() {\n"
503         "  v = vec2(instanceName1.f1, instanceName2[0].f2);\n"
504         "  gl_Position = vec4(position, 0, 1);\n"
505         "}";
506 
507     constexpr char kFS[] =
508         "#version 300 es\n"
509         "precision highp float;\n"
510         "in vec2 v;\n"
511         "out vec4 color;\n"
512         "void main() {\n"
513         "  color = vec4(v, 0, 1);\n"
514         "}";
515 
516     ANGLE_GL_PROGRAM(program, kVS, kFS);
517 
518     GLint activeUniformBlocks;
519     glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &activeUniformBlocks);
520     ASSERT_EQ(2, activeUniformBlocks);
521 
522     GLuint index = glGetUniformBlockIndex(program, "blockName1");
523     EXPECT_NE(GL_INVALID_INDEX, index);
524     ASSERT_GL_NO_ERROR();
525 
526     index = glGetUniformBlockIndex(program, "blockName2[0]");
527     EXPECT_NE(GL_INVALID_INDEX, index);
528     ASSERT_GL_NO_ERROR();
529 
530     GLint activeUniforms;
531     glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &activeUniforms);
532 
533     ASSERT_EQ(2, activeUniforms);
534 
535     GLint size;
536     GLenum type;
537     GLint maxLength;
538     GLsizei length;
539 
540     glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
541     std::vector<GLchar> strUniformNameBuffer(maxLength + 1, 0);
542     const GLchar *uniformNames[1];
543     uniformNames[0] = "blockName1.f1";
544     glGetUniformIndices(program, 1, uniformNames, &index);
545     EXPECT_NE(GL_INVALID_INDEX, index);
546     ASSERT_GL_NO_ERROR();
547     glGetActiveUniform(program, index, maxLength, &length, &size, &type, &strUniformNameBuffer[0]);
548     EXPECT_EQ(1, size);
549     EXPECT_GLENUM_EQ(GL_FLOAT, type);
550     EXPECT_EQ("blockName1.f1", std::string(&strUniformNameBuffer[0]));
551 
552     uniformNames[0] = "blockName2.f2";
553     glGetUniformIndices(program, 1, uniformNames, &index);
554     EXPECT_NE(GL_INVALID_INDEX, index);
555     ASSERT_GL_NO_ERROR();
556     glGetActiveUniform(program, index, maxLength, &length, &size, &type, &strUniformNameBuffer[0]);
557     EXPECT_EQ(1, size);
558     EXPECT_GLENUM_EQ(GL_FLOAT, type);
559     EXPECT_EQ("blockName2.f2", std::string(&strUniformNameBuffer[0]));
560 }
561 
562 // Tests active uniforms and blocks when the layout is std140, shared and packed.
TEST_P(UniformBufferTest,ActiveUniformNumberAndName)563 TEST_P(UniformBufferTest, ActiveUniformNumberAndName)
564 {
565     constexpr char kVS[] =
566         "#version 300 es\n"
567         "in vec2 position;\n"
568         "out float v;\n"
569         "struct S {\n"
570         "  highp ivec3 a;\n"
571         "  mediump ivec2 b[4];\n"
572         "};\n"
573         "layout(std140) uniform blockName0 {\n"
574         "  S s0;\n"
575         "  lowp vec2 v0;\n"
576         "  S s1[2];\n"
577         "  highp uint u0;\n"
578         "};\n"
579         "layout(std140) uniform blockName1 {\n"
580         "  float f1;\n"
581         "  bool b1;\n"
582         "} instanceName1;\n"
583         "layout(shared) uniform blockName2 {\n"
584         "  float f2;\n"
585         "};\n"
586         "layout(packed) uniform blockName3 {\n"
587         "  float f3;\n"
588         "};\n"
589         "void main() {\n"
590         "  v = instanceName1.f1;\n"
591         "  gl_Position = vec4(position, 0, 1);\n"
592         "}";
593 
594     constexpr char kFS[] =
595         "#version 300 es\n"
596         "precision highp float;\n"
597         "in float v;\n"
598         "out vec4 color;\n"
599         "void main() {\n"
600         "  color = vec4(v, 0, 0, 1);\n"
601         "}";
602 
603     ANGLE_GL_PROGRAM(program, kVS, kFS);
604 
605     // Note that the packed |blockName3| might (or might not) be optimized out.
606     GLint activeUniforms;
607     glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &activeUniforms);
608     EXPECT_GE(activeUniforms, 11);
609 
610     GLint activeUniformBlocks;
611     glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &activeUniformBlocks);
612     EXPECT_GE(activeUniformBlocks, 3);
613 
614     GLint maxLength, size;
615     GLenum type;
616     GLsizei length;
617     GLuint index;
618     const GLchar *uniformNames[1];
619     glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
620     std::vector<GLchar> strBuffer(maxLength + 1, 0);
621 
622     uniformNames[0] = "s0.a";
623     glGetUniformIndices(program, 1, uniformNames, &index);
624     EXPECT_NE(GL_INVALID_INDEX, index);
625     ASSERT_GL_NO_ERROR();
626     glGetActiveUniform(program, index, maxLength, &length, &size, &type, &strBuffer[0]);
627     EXPECT_EQ(1, size);
628     EXPECT_EQ("s0.a", std::string(&strBuffer[0]));
629 
630     uniformNames[0] = "s0.b[0]";
631     glGetUniformIndices(program, 1, uniformNames, &index);
632     EXPECT_NE(GL_INVALID_INDEX, index);
633     ASSERT_GL_NO_ERROR();
634     glGetActiveUniform(program, index, maxLength, &length, &size, &type, &strBuffer[0]);
635     ASSERT_GL_NO_ERROR();
636     EXPECT_EQ(4, size);
637     EXPECT_EQ("s0.b[0]", std::string(&strBuffer[0]));
638 
639     uniformNames[0] = "v0";
640     glGetUniformIndices(program, 1, uniformNames, &index);
641     EXPECT_NE(GL_INVALID_INDEX, index);
642     ASSERT_GL_NO_ERROR();
643     glGetActiveUniform(program, index, maxLength, &length, &size, &type, &strBuffer[0]);
644     ASSERT_GL_NO_ERROR();
645     EXPECT_EQ(1, size);
646     EXPECT_EQ("v0", std::string(&strBuffer[0]));
647 
648     uniformNames[0] = "s1[0].a";
649     glGetUniformIndices(program, 1, uniformNames, &index);
650     EXPECT_NE(GL_INVALID_INDEX, index);
651     ASSERT_GL_NO_ERROR();
652     glGetActiveUniform(program, index, maxLength, &length, &size, &type, &strBuffer[0]);
653     ASSERT_GL_NO_ERROR();
654     EXPECT_EQ(1, size);
655     EXPECT_EQ("s1[0].a", std::string(&strBuffer[0]));
656 
657     uniformNames[0] = "s1[0].b[0]";
658     glGetUniformIndices(program, 1, uniformNames, &index);
659     EXPECT_NE(GL_INVALID_INDEX, index);
660     ASSERT_GL_NO_ERROR();
661     glGetActiveUniform(program, index, maxLength, &length, &size, &type, &strBuffer[0]);
662     ASSERT_GL_NO_ERROR();
663     EXPECT_EQ(4, size);
664     EXPECT_EQ("s1[0].b[0]", std::string(&strBuffer[0]));
665 
666     uniformNames[0] = "s1[1].a";
667     glGetUniformIndices(program, 1, uniformNames, &index);
668     EXPECT_NE(GL_INVALID_INDEX, index);
669     ASSERT_GL_NO_ERROR();
670     glGetActiveUniform(program, index, maxLength, &length, &size, &type, &strBuffer[0]);
671     ASSERT_GL_NO_ERROR();
672     EXPECT_EQ(1, size);
673     EXPECT_EQ("s1[1].a", std::string(&strBuffer[0]));
674 
675     uniformNames[0] = "s1[1].b[0]";
676     glGetUniformIndices(program, 1, uniformNames, &index);
677     EXPECT_NE(GL_INVALID_INDEX, index);
678     ASSERT_GL_NO_ERROR();
679     glGetActiveUniform(program, index, maxLength, &length, &size, &type, &strBuffer[0]);
680     ASSERT_GL_NO_ERROR();
681     EXPECT_EQ(4, size);
682     EXPECT_EQ("s1[1].b[0]", std::string(&strBuffer[0]));
683 
684     uniformNames[0] = "u0";
685     glGetUniformIndices(program, 1, uniformNames, &index);
686     EXPECT_NE(GL_INVALID_INDEX, index);
687     ASSERT_GL_NO_ERROR();
688     glGetActiveUniform(program, index, maxLength, &length, &size, &type, &strBuffer[0]);
689     ASSERT_GL_NO_ERROR();
690     EXPECT_EQ(1, size);
691     EXPECT_EQ("u0", std::string(&strBuffer[0]));
692 
693     uniformNames[0] = "blockName1.f1";
694     glGetUniformIndices(program, 1, uniformNames, &index);
695     EXPECT_NE(GL_INVALID_INDEX, index);
696     ASSERT_GL_NO_ERROR();
697     glGetActiveUniform(program, index, maxLength, &length, &size, &type, &strBuffer[0]);
698     ASSERT_GL_NO_ERROR();
699     EXPECT_EQ(1, size);
700     EXPECT_EQ("blockName1.f1", std::string(&strBuffer[0]));
701 
702     uniformNames[0] = "blockName1.b1";
703     glGetUniformIndices(program, 1, uniformNames, &index);
704     EXPECT_NE(GL_INVALID_INDEX, index);
705     ASSERT_GL_NO_ERROR();
706     glGetActiveUniform(program, index, maxLength, &length, &size, &type, &strBuffer[0]);
707     ASSERT_GL_NO_ERROR();
708     EXPECT_EQ(1, size);
709     EXPECT_EQ("blockName1.b1", std::string(&strBuffer[0]));
710 
711     uniformNames[0] = "f2";
712     glGetUniformIndices(program, 1, uniformNames, &index);
713     EXPECT_NE(GL_INVALID_INDEX, index);
714     ASSERT_GL_NO_ERROR();
715     glGetActiveUniform(program, index, maxLength, &length, &size, &type, &strBuffer[0]);
716     ASSERT_GL_NO_ERROR();
717     EXPECT_EQ(1, size);
718     EXPECT_EQ("f2", std::string(&strBuffer[0]));
719 }
720 
721 // Test that using a very large buffer to back a small uniform block works OK.
TEST_P(UniformBufferTest,VeryLarge)722 TEST_P(UniformBufferTest, VeryLarge)
723 {
724     glClear(GL_COLOR_BUFFER_BIT);
725     float floatData[4] = {0.5f, 0.75f, 0.25f, 1.0f};
726 
727     GLsizei bigSize = 4096 * 64;
728     std::vector<GLubyte> zero(bigSize, 0);
729 
730     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
731     glBufferData(GL_UNIFORM_BUFFER, bigSize, zero.data(), GL_STATIC_DRAW);
732     glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(float) * 4, floatData);
733 
734     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
735 
736     glUniformBlockBinding(mProgram, mUniformBufferIndex, 0);
737     drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
738 
739     ASSERT_GL_NO_ERROR();
740     EXPECT_PIXEL_NEAR(0, 0, 128, 191, 64, 255, 1);
741 }
742 
743 // Test that readback from a very large uniform buffer works OK.
TEST_P(UniformBufferTest,VeryLargeReadback)744 TEST_P(UniformBufferTest, VeryLargeReadback)
745 {
746     glClear(GL_COLOR_BUFFER_BIT);
747 
748     // Generate some random data.
749     GLsizei bigSize = 4096 * 64;
750     std::vector<GLubyte> expectedData(bigSize);
751     for (GLsizei index = 0; index < bigSize; ++index)
752     {
753         expectedData[index] = static_cast<GLubyte>(index);
754     }
755 
756     // Initialize the GL buffer.
757     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
758     glBufferData(GL_UNIFORM_BUFFER, bigSize, expectedData.data(), GL_STATIC_DRAW);
759 
760     // Do a small update.
761     GLsizei smallSize              = sizeof(float) * 4;
762     std::array<float, 4> floatData = {{0.5f, 0.75f, 0.25f, 1.0f}};
763     memcpy(expectedData.data(), floatData.data(), smallSize);
764 
765     glBufferSubData(GL_UNIFORM_BUFFER, 0, smallSize, expectedData.data());
766 
767     // Draw with the buffer.
768     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
769     glUniformBlockBinding(mProgram, mUniformBufferIndex, 0);
770     drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
771 
772     ASSERT_GL_NO_ERROR();
773     EXPECT_PIXEL_NEAR(0, 0, 128, 191, 64, 255, 1);
774 
775     // Read back the large buffer data.
776     const void *mapPtr = glMapBufferRange(GL_UNIFORM_BUFFER, 0, bigSize, GL_MAP_READ_BIT);
777     ASSERT_GL_NO_ERROR();
778     const GLubyte *bytePtr = reinterpret_cast<const GLubyte *>(mapPtr);
779     std::vector<GLubyte> actualData(bytePtr, bytePtr + bigSize);
780     EXPECT_EQ(expectedData, actualData);
781 
782     glUnmapBuffer(GL_UNIFORM_BUFFER);
783 }
784 
785 // Test drawing with different sized uniform blocks from the same UBO, drawing a smaller uniform
786 // block before larger one.
TEST_P(UniformBufferTest,MultipleSizesSmallBeforeBig)787 TEST_P(UniformBufferTest, MultipleSizesSmallBeforeBig)
788 {
789     constexpr size_t kSizeOfVec4  = 4 * sizeof(float);
790     constexpr char kUniformName[] = "uni";
791     constexpr char kFS1[]         = R"(#version 300 es
792 precision highp float;
793 layout(std140) uniform uni {
794     bool b;
795 };
796 
797 out vec4 fragColor;
798 void main() {
799     fragColor = b ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
800 })";
801 
802     constexpr char kFS2[] = R"(#version 300 es
803 precision highp float;
804 layout(std140) uniform uni {
805     bool b[2];
806     vec4 v;
807 };
808 
809 out vec4 fragColor;
810 void main() {
811     fragColor = v;
812 })";
813 
814     GLint offsetAlignmentInBytes;
815     glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &offsetAlignmentInBytes);
816     ASSERT_EQ(offsetAlignmentInBytes % kSizeOfVec4, 0U);
817     GLint offsetAlignmentInVec4 = offsetAlignmentInBytes / kSizeOfVec4;
818 
819     // Insert padding required by implementation to have first unform block at a non-zero
820     // offset.
821     int initialPadding = rx::roundUp(3, offsetAlignmentInVec4);
822     std::vector<float> uboData;
823     for (int n = 0; n < initialPadding; ++n)
824     {
825         uboData.insert(uboData.end(), {0.0f, 0.0f, 0.0f, 0.0f});
826     }
827 
828     // First uniform block - a single bool
829     uboData.insert(uboData.end(), {1.0f, 0.0f, 0.0f, 0.0f});
830 
831     // Insert padding required by implementation to align second uniform block.
832     for (int n = 0; n < offsetAlignmentInVec4 - 1; ++n)
833     {
834         uboData.insert(uboData.end(), {0.0f, 0.0f, 0.0f, 0.0f});
835     }
836 
837     // Second uniform block
838     uboData.insert(uboData.end(), {0.0f, 0.0f, 0.0f, 0.0f});
839     uboData.insert(uboData.end(), {1.0f, 0.0f, 0.0f, 0.0f});
840     uboData.insert(uboData.end(), {0.0f, 1.0f, 0.0f, 1.0f});
841 
842     ANGLE_GL_PROGRAM(program1, essl3_shaders::vs::Simple(), kFS1);
843     ANGLE_GL_PROGRAM(program2, essl3_shaders::vs::Simple(), kFS2);
844 
845     // UBO containing 2 different uniform blocks
846     GLBuffer ubo;
847     glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo);
848     glBufferData(GL_UNIFORM_BUFFER, uboData.size() * sizeof(float), uboData.data(), GL_STATIC_DRAW);
849     ASSERT_GL_NO_ERROR();
850 
851     // Clear
852     glClear(GL_COLOR_BUFFER_BIT);
853 
854     // Draw with first uniform block
855     GLuint index = glGetUniformBlockIndex(program1, kUniformName);
856     EXPECT_NE(GL_INVALID_INDEX, index);
857     ASSERT_GL_NO_ERROR();
858 
859     glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo, initialPadding * kSizeOfVec4, kSizeOfVec4);
860     ASSERT_GL_NO_ERROR();
861 
862     glUniformBlockBinding(program1, index, 0);
863     drawQuad(program1, essl3_shaders::PositionAttrib(), 0.5f);
864     ASSERT_GL_NO_ERROR();
865 
866     EXPECT_PIXEL_NEAR(0, 0, 0, 255, 0, 255, 1);
867 
868     // Draw with second uniform block
869     index = glGetUniformBlockIndex(program2, kUniformName);
870     EXPECT_NE(GL_INVALID_INDEX, index);
871     ASSERT_GL_NO_ERROR();
872 
873     glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo,
874                       (initialPadding + offsetAlignmentInVec4) * kSizeOfVec4, 3 * kSizeOfVec4);
875     ASSERT_GL_NO_ERROR();
876 
877     glUniformBlockBinding(program2, index, 0);
878     drawQuad(program2, essl3_shaders::PositionAttrib(), 0.5f);
879     ASSERT_GL_NO_ERROR();
880 
881     EXPECT_PIXEL_NEAR(0, 0, 0, 255, 0, 255, 1);
882 }
883 
884 class UniformBufferTest31 : public ANGLETest<>
885 {
886   protected:
UniformBufferTest31()887     UniformBufferTest31()
888     {
889         setWindowWidth(128);
890         setWindowHeight(128);
891         setConfigRedBits(8);
892         setConfigGreenBits(8);
893         setConfigBlueBits(8);
894         setConfigAlphaBits(8);
895     }
896 };
897 
898 // Test uniform block bindings greater than GL_MAX_UNIFORM_BUFFER_BINDINGS cause compile error.
TEST_P(UniformBufferTest31,MaxUniformBufferBindingsExceeded)899 TEST_P(UniformBufferTest31, MaxUniformBufferBindingsExceeded)
900 {
901     GLint maxUniformBufferBindings;
902     glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &maxUniformBufferBindings);
903     std::string source =
904         "#version 310 es\n"
905         "in vec4 position;\n"
906         "layout(binding = ";
907     std::stringstream ss;
908     ss << maxUniformBufferBindings;
909     source = source + ss.str() +
910              ") uniform uni {\n"
911              "    vec4 color;\n"
912              "};\n"
913              "void main()\n"
914              "{\n"
915              "    gl_Position = position;\n"
916              "}";
917     GLuint shader = CompileShader(GL_VERTEX_SHADER, source.c_str());
918     EXPECT_EQ(0u, shader);
919 }
920 
921 // Test uniform block bindings specified by layout in shader work properly.
TEST_P(UniformBufferTest31,UniformBufferBindings)922 TEST_P(UniformBufferTest31, UniformBufferBindings)
923 {
924     constexpr char kVS[] =
925         "#version 310 es\n"
926         "in vec4 position;\n"
927         "void main()\n"
928         "{\n"
929         "    gl_Position = position;\n"
930         "}";
931     constexpr char kFS[] =
932         "#version 310 es\n"
933         "precision highp float;\n"
934         "layout(binding = 2) uniform uni {\n"
935         "    vec4 color;\n"
936         "};\n"
937         "out vec4 fragColor;\n"
938         "void main()\n"
939         "{"
940         "    fragColor = color;\n"
941         "}";
942 
943     ANGLE_GL_PROGRAM(program, kVS, kFS);
944     GLuint uniformBufferIndex = glGetUniformBlockIndex(program, "uni");
945     ASSERT_NE(GL_INVALID_INDEX, uniformBufferIndex);
946     GLBuffer uniformBuffer;
947 
948     int px = getWindowWidth() / 2;
949     int py = getWindowHeight() / 2;
950 
951     ASSERT_GL_NO_ERROR();
952 
953     // Let's create a buffer which contains one vec4.
954     GLuint vec4Size = 4 * sizeof(float);
955     std::vector<char> v(vec4Size);
956     float *first = reinterpret_cast<float *>(v.data());
957 
958     first[0] = 10.f / 255.f;
959     first[1] = 20.f / 255.f;
960     first[2] = 30.f / 255.f;
961     first[3] = 40.f / 255.f;
962 
963     glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer);
964     glBufferData(GL_UNIFORM_BUFFER, vec4Size, v.data(), GL_STATIC_DRAW);
965 
966     EXPECT_GL_NO_ERROR();
967 
968     glBindBufferBase(GL_UNIFORM_BUFFER, 2, uniformBuffer);
969     drawQuad(program, "position", 0.5f);
970     EXPECT_GL_NO_ERROR();
971     EXPECT_PIXEL_EQ(px, py, 10, 20, 30, 40);
972 
973     // Clear the framebuffer
974     glClearColor(0.0, 0.0, 0.0, 0.0);
975     glClear(GL_COLOR_BUFFER_BIT);
976     EXPECT_PIXEL_EQ(px, py, 0, 0, 0, 0);
977 
978     // Try to bind the buffer to another binding point
979     glUniformBlockBinding(program, uniformBufferIndex, 5);
980     glBindBufferBase(GL_UNIFORM_BUFFER, 5, uniformBuffer);
981     drawQuad(program, "position", 0.5f);
982     EXPECT_GL_NO_ERROR();
983     EXPECT_PIXEL_EQ(px, py, 10, 20, 30, 40);
984 }
985 
986 // Test uniform blocks used as instanced array take next binding point for each subsequent element.
TEST_P(UniformBufferTest31,ConsecutiveBindingsForBlockArray)987 TEST_P(UniformBufferTest31, ConsecutiveBindingsForBlockArray)
988 {
989     constexpr char kFS[] =
990         "#version 310 es\n"
991         "precision highp float;\n"
992         "layout(binding = 2) uniform uni {\n"
993         "    vec4 color;\n"
994         "} blocks[2];\n"
995         "out vec4 fragColor;\n"
996         "void main()\n"
997         "{\n"
998         "    fragColor = blocks[0].color + blocks[1].color;\n"
999         "}";
1000 
1001     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
1002     std::array<GLBuffer, 2> uniformBuffers;
1003 
1004     int px = getWindowWidth() / 2;
1005     int py = getWindowHeight() / 2;
1006 
1007     ASSERT_GL_NO_ERROR();
1008 
1009     // Let's create a buffer which contains one vec4.
1010     GLuint vec4Size = 4 * sizeof(float);
1011     std::vector<char> v(vec4Size);
1012     float *first = reinterpret_cast<float *>(v.data());
1013 
1014     first[0] = 10.f / 255.f;
1015     first[1] = 20.f / 255.f;
1016     first[2] = 30.f / 255.f;
1017     first[3] = 40.f / 255.f;
1018 
1019     glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffers[0]);
1020     glBufferData(GL_UNIFORM_BUFFER, vec4Size, v.data(), GL_STATIC_DRAW);
1021     EXPECT_GL_NO_ERROR();
1022     glBindBufferBase(GL_UNIFORM_BUFFER, 2, uniformBuffers[0]);
1023     ASSERT_GL_NO_ERROR();
1024     glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffers[1]);
1025     glBufferData(GL_UNIFORM_BUFFER, vec4Size, v.data(), GL_STATIC_DRAW);
1026     EXPECT_GL_NO_ERROR();
1027     glBindBufferBase(GL_UNIFORM_BUFFER, 3, uniformBuffers[1]);
1028 
1029     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f);
1030     EXPECT_GL_NO_ERROR();
1031     EXPECT_PIXEL_EQ(px, py, 20, 40, 60, 80);
1032 }
1033 
1034 // Test the layout qualifier binding must be both specified(ESSL 3.10.4 section 9.2).
TEST_P(UniformBufferTest31,BindingMustBeBothSpecified)1035 TEST_P(UniformBufferTest31, BindingMustBeBothSpecified)
1036 {
1037     constexpr char kVS[] =
1038         "#version 310 es\n"
1039         "in vec4 position;\n"
1040         "uniform uni\n"
1041         "{\n"
1042         "    vec4 color;\n"
1043         "} block;\n"
1044         "void main()\n"
1045         "{\n"
1046         "    gl_Position = position + block.color;\n"
1047         "}";
1048     constexpr char kFS[] =
1049         "#version 310 es\n"
1050         "precision highp float;\n"
1051         "layout(binding = 0) uniform uni\n"
1052         "{\n"
1053         "    vec4 color;\n"
1054         "} block;\n"
1055         "out vec4 fragColor;\n"
1056         "void main()\n"
1057         "{\n"
1058         "    fragColor = block.color;\n"
1059         "}";
1060     GLuint program = CompileProgram(kVS, kFS);
1061     ASSERT_EQ(0u, program);
1062 }
1063 
1064 // Test that uploading data to buffer that's in use then using it as indirect buffer works.
TEST_P(UniformBufferTest31,UseAsUBOThenUpdateThenDrawIndirect)1065 TEST_P(UniformBufferTest31, UseAsUBOThenUpdateThenDrawIndirect)
1066 {
1067     // http://anglebug.com/42264362
1068     ANGLE_SKIP_TEST_IF(IsD3D11());
1069 
1070     // http://anglebug.com/42264411
1071     ANGLE_SKIP_TEST_IF(IsVulkan() && IsPixel2());
1072 
1073     const std::array<uint32_t, 4> kInitialData = {100, 200, 300, 400};
1074     const std::array<uint32_t, 4> kUpdateData  = {4, 1, 0, 0};
1075 
1076     GLBuffer buffer;
1077     glBindBuffer(GL_UNIFORM_BUFFER, buffer);
1078     glBufferData(GL_UNIFORM_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
1079     glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
1080     EXPECT_GL_NO_ERROR();
1081 
1082     constexpr char kVerifyUBO[] = R"(#version 310 es
1083 precision mediump float;
1084 layout(binding = 0) uniform block {
1085     uvec4 data;
1086 } ubo;
1087 out vec4 colorOut;
1088 void main()
1089 {
1090     if (all(equal(ubo.data, uvec4(100, 200, 300, 400))))
1091         colorOut = vec4(0, 1.0, 0, 1.0);
1092     else
1093         colorOut = vec4(1.0, 0, 0, 1.0);
1094 })";
1095 
1096     ANGLE_GL_PROGRAM(verifyUbo, essl31_shaders::vs::Simple(), kVerifyUBO);
1097     drawQuad(verifyUbo, essl31_shaders::PositionAttrib(), 0.5);
1098     EXPECT_GL_NO_ERROR();
1099 
1100     // Update buffer data
1101     glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kInitialData), kUpdateData.data());
1102     EXPECT_GL_NO_ERROR();
1103 
1104     // Draw indirect using the updated parameters
1105     constexpr char kVS[] = R"(#version 310 es
1106 void main()
1107 {
1108     // gl_VertexID    x    y
1109     //      0        -1   -1
1110     //      1         1   -1
1111     //      2        -1    1
1112     //      3         1    1
1113     int bit0 = gl_VertexID & 1;
1114     int bit1 = gl_VertexID >> 1;
1115     gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, 0, 1);
1116 })";
1117 
1118     constexpr char kFS[] = R"(#version 310 es
1119 precision mediump float;
1120 out vec4 colorOut;
1121 void main()
1122 {
1123     colorOut = vec4(0, 0, 1.0, 1.0);
1124 })";
1125 
1126     ANGLE_GL_PROGRAM(draw, kVS, kFS);
1127     glUseProgram(draw);
1128 
1129     glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer);
1130     EXPECT_GL_NO_ERROR();
1131 
1132     GLVertexArray vao;
1133     glBindVertexArray(vao);
1134 
1135     glEnable(GL_BLEND);
1136     glBlendFunc(GL_ONE, GL_ONE);
1137     glDrawArraysIndirect(GL_TRIANGLE_STRIP, nullptr);
1138     EXPECT_GL_NO_ERROR();
1139 
1140     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
1141 }
1142 
1143 // Test four bindings of the same uniform buffer.
TEST_P(UniformBufferTest31,FourBindingsSameBuffer)1144 TEST_P(UniformBufferTest31, FourBindingsSameBuffer)
1145 {
1146     // Create a program with accesses from four UBO binding points.
1147     constexpr char kFS[] = R"(#version 310 es
1148 precision mediump float;
1149 layout (binding = 0) uniform block0 {
1150     vec4 color;
1151 } b0;
1152 layout (binding = 1) uniform block1 {
1153     vec4 color;
1154 } b1;
1155 layout (binding = 2) uniform block2 {
1156     vec4 color;
1157 } b2;
1158 layout (binding = 3) uniform block3 {
1159     vec4 color;
1160 } b3;
1161 
1162 out vec4 outColor;
1163 
1164 void main() {
1165     outColor = b0.color + b1.color + b2.color + b3.color;
1166 })";
1167 
1168     // Create a UBO.
1169     constexpr GLfloat uboData[4] = {0.0, 0.25, 0.0, 0.25};
1170     GLBuffer ubo;
1171     glBindBuffer(GL_UNIFORM_BUFFER, ubo);
1172     glBufferData(GL_UNIFORM_BUFFER, sizeof(uboData), uboData, GL_STATIC_READ);
1173 
1174     // Bind the same UBO to all four binding points.
1175     glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo);
1176     glBindBufferBase(GL_UNIFORM_BUFFER, 1, ubo);
1177     glBindBufferBase(GL_UNIFORM_BUFFER, 2, ubo);
1178     glBindBufferBase(GL_UNIFORM_BUFFER, 3, ubo);
1179 
1180     ANGLE_GL_PROGRAM(uboProgram, essl31_shaders::vs::Simple(), kFS);
1181     drawQuad(uboProgram, essl1_shaders::PositionAttrib(), 0.5f, 1.0f);
1182     EXPECT_GL_NO_ERROR();
1183 
1184     // Four {0, 0.25, 0, 0.25} pixels should sum to green.
1185     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1186 }
1187 
1188 // Test with a block containing an array of structs.
TEST_P(UniformBufferTest,BlockContainingArrayOfStructs)1189 TEST_P(UniformBufferTest, BlockContainingArrayOfStructs)
1190 {
1191     constexpr char kFS[] =
1192         "#version 300 es\n"
1193         "precision highp float;\n"
1194         "out vec4 my_FragColor;\n"
1195         "struct light_t {\n"
1196         "    vec4 intensity;\n"
1197         "};\n"
1198         "const int maxLights = 2;\n"
1199         "layout(std140) uniform lightData { light_t lights[maxLights]; };\n"
1200         "vec4 processLight(vec4 lighting, light_t light)\n"
1201         "{\n"
1202         "    return lighting + light.intensity;\n"
1203         "}\n"
1204         "void main()\n"
1205         "{\n"
1206         "    vec4 lighting = vec4(0, 0, 0, 1);\n"
1207         "    for (int n = 0; n < maxLights; n++)\n"
1208         "    {\n"
1209         "        lighting = processLight(lighting, lights[n]);\n"
1210         "    }\n"
1211         "    my_FragColor = lighting;\n"
1212         "}\n";
1213 
1214     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
1215     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "lightData");
1216 
1217     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
1218     const GLsizei kStructCount        = 2;
1219     const GLsizei kVectorElementCount = 4;
1220     const GLsizei kBytesPerElement    = 4;
1221     const GLsizei kDataSize           = kStructCount * kVectorElementCount * kBytesPerElement;
1222     std::vector<GLubyte> v(kDataSize, 0);
1223     float *vAsFloat = reinterpret_cast<float *>(v.data());
1224 
1225     vAsFloat[1]                       = 0.5f;
1226     vAsFloat[kVectorElementCount + 1] = 0.5f;
1227 
1228     glBufferData(GL_UNIFORM_BUFFER, kDataSize, v.data(), GL_STATIC_DRAW);
1229 
1230     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
1231     glUniformBlockBinding(program, uniformBufferIndex, 0);
1232     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1233     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1234 }
1235 
1236 // Test with a block instance array containing an array of structs.
TEST_P(UniformBufferTest,BlockArrayContainingArrayOfStructs)1237 TEST_P(UniformBufferTest, BlockArrayContainingArrayOfStructs)
1238 {
1239     constexpr char kFS[] =
1240         R"(#version 300 es
1241 
1242         precision highp float;
1243         out vec4 my_FragColor;
1244         struct light_t
1245         {
1246             vec4 intensity;
1247         };
1248 
1249         layout(std140) uniform lightData { light_t lights[2]; } buffers[2];
1250 
1251         vec4 processLight(vec4 lighting, light_t light)
1252         {
1253             return lighting + light.intensity;
1254         }
1255         void main()
1256         {
1257             vec4 lighting = vec4(0, 0, 0, 1);
1258             lighting = processLight(lighting, buffers[0].lights[0]);
1259             lighting = processLight(lighting, buffers[1].lights[1]);
1260             my_FragColor = lighting;
1261         })";
1262 
1263     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
1264     GLint uniformBufferIndex  = glGetUniformBlockIndex(program, "lightData[0]");
1265     GLint uniformBuffer2Index = glGetUniformBlockIndex(program, "lightData[1]");
1266 
1267     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
1268     const GLsizei kStructCount        = 2;
1269     const GLsizei kVectorElementCount = 4;
1270     const GLsizei kBytesPerElement    = 4;
1271     const GLsizei kDataSize           = kStructCount * kVectorElementCount * kBytesPerElement;
1272     std::vector<GLubyte> v(kDataSize, 0);
1273     float *vAsFloat = reinterpret_cast<float *>(v.data());
1274 
1275     // In the first struct/vector of the first block
1276     vAsFloat[1] = 0.5f;
1277 
1278     glBufferData(GL_UNIFORM_BUFFER, kDataSize, v.data(), GL_STATIC_DRAW);
1279 
1280     GLBuffer uniformBuffer2;
1281     glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer2);
1282 
1283     vAsFloat[1] = 0.0f;
1284     // In the second struct/vector of the second block
1285     vAsFloat[kVectorElementCount + 1] = 0.5f;
1286     glBufferData(GL_UNIFORM_BUFFER, kDataSize, v.data(), GL_STATIC_DRAW);
1287 
1288     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
1289     glBindBufferBase(GL_UNIFORM_BUFFER, 1, uniformBuffer2);
1290     glUniformBlockBinding(program, uniformBufferIndex, 0);
1291     glUniformBlockBinding(program, uniformBuffer2Index, 1);
1292     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1293     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1294 }
1295 
1296 // Test with a block containing an array of structs containing arrays.
TEST_P(UniformBufferTest,BlockContainingArrayOfStructsContainingArrays)1297 TEST_P(UniformBufferTest, BlockContainingArrayOfStructsContainingArrays)
1298 {
1299     constexpr char kFS[] =
1300         R"(#version 300 es
1301         precision highp float;
1302         out vec4 my_FragColor;
1303         struct light_t
1304         {
1305             vec4 intensity[3];
1306         };
1307         const int maxLights = 2;
1308         layout(std140) uniform lightData { light_t lights[maxLights]; };
1309         vec4 processLight(vec4 lighting, light_t light)
1310         {
1311             return lighting + light.intensity[1];
1312         }
1313         void main()
1314         {
1315             vec4 lighting = vec4(0, 0, 0, 1);
1316             lighting = processLight(lighting, lights[0]);
1317             lighting = processLight(lighting, lights[1]);
1318             my_FragColor = lighting;
1319         })";
1320 
1321     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
1322     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "lightData");
1323 
1324     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
1325     const GLsizei kStructCount       = 2;
1326     const GLsizei kVectorsPerStruct  = 3;
1327     const GLsizei kElementsPerVector = 4;
1328     const GLsizei kBytesPerElement   = 4;
1329     const GLsizei kDataSize =
1330         kStructCount * kVectorsPerStruct * kElementsPerVector * kBytesPerElement;
1331     std::vector<GLubyte> v(kDataSize, 0);
1332     float *vAsFloat = reinterpret_cast<float *>(v.data());
1333 
1334     vAsFloat[kElementsPerVector + 1]                                          = 0.5f;
1335     vAsFloat[kVectorsPerStruct * kElementsPerVector + kElementsPerVector + 1] = 0.5f;
1336 
1337     glBufferData(GL_UNIFORM_BUFFER, kDataSize, v.data(), GL_STATIC_DRAW);
1338     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
1339     glUniformBlockBinding(program, uniformBufferIndex, 0);
1340     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1341     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1342 }
1343 
1344 // Test with a block containing nested structs.
TEST_P(UniformBufferTest,BlockContainingNestedStructs)1345 TEST_P(UniformBufferTest, BlockContainingNestedStructs)
1346 {
1347     constexpr char kFS[] =
1348         "#version 300 es\n"
1349         "precision highp float;\n"
1350         "out vec4 my_FragColor;\n"
1351         "struct light_t {\n"
1352         "    vec4 intensity;\n"
1353         "};\n"
1354         "struct lightWrapper_t {\n"
1355         "    light_t light;\n"
1356         "};\n"
1357         "const int maxLights = 2;\n"
1358         "layout(std140) uniform lightData { lightWrapper_t lightWrapper; };\n"
1359         "vec4 processLight(vec4 lighting, lightWrapper_t aLightWrapper)\n"
1360         "{\n"
1361         "    return lighting + aLightWrapper.light.intensity;\n"
1362         "}\n"
1363         "void main()\n"
1364         "{\n"
1365         "    vec4 lighting = vec4(0, 0, 0, 1);\n"
1366         "    for (int n = 0; n < maxLights; n++)\n"
1367         "    {\n"
1368         "        lighting = processLight(lighting, lightWrapper);\n"
1369         "    }\n"
1370         "    my_FragColor = lighting;\n"
1371         "}\n";
1372 
1373     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
1374     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "lightData");
1375 
1376     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
1377     const GLsizei kVectorsPerStruct  = 3;
1378     const GLsizei kElementsPerVector = 4;
1379     const GLsizei kBytesPerElement   = 4;
1380     const GLsizei kDataSize          = kVectorsPerStruct * kElementsPerVector * kBytesPerElement;
1381     std::vector<GLubyte> v(kDataSize, 0);
1382     float *vAsFloat = reinterpret_cast<float *>(v.data());
1383 
1384     vAsFloat[1] = 1.0f;
1385 
1386     glBufferData(GL_UNIFORM_BUFFER, kDataSize, v.data(), GL_STATIC_DRAW);
1387     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
1388     glUniformBlockBinding(program, uniformBufferIndex, 0);
1389     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1390     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1391 }
1392 
1393 // Tests GetUniformBlockIndex return value on error.
TEST_P(UniformBufferTest,GetUniformBlockIndexDefaultReturn)1394 TEST_P(UniformBufferTest, GetUniformBlockIndexDefaultReturn)
1395 {
1396     ASSERT_FALSE(glIsProgram(99));
1397     EXPECT_EQ(GL_INVALID_INDEX, glGetUniformBlockIndex(99, "farts"));
1398     EXPECT_GL_ERROR(GL_INVALID_VALUE);
1399 }
1400 
1401 // Block names can be reserved names in GLSL, as long as they're not reserved in GLSL ES.
TEST_P(UniformBufferTest,UniformBlockReservedOpenGLName)1402 TEST_P(UniformBufferTest, UniformBlockReservedOpenGLName)
1403 {
1404     constexpr char kFS[] =
1405         "#version 300 es\n"
1406         "precision highp float;\n"
1407         "out vec4 my_FragColor;\n"
1408         "layout(std140) uniform buffer { vec4 color; };\n"
1409         "void main()\n"
1410         "{\n"
1411         "    my_FragColor = color;\n"
1412         "}\n";
1413 
1414     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
1415     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "buffer");
1416 
1417     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
1418     const GLsizei kElementsPerVector = 4;
1419     const GLsizei kBytesPerElement   = 4;
1420     const GLsizei kDataSize          = kElementsPerVector * kBytesPerElement;
1421     std::vector<GLubyte> v(kDataSize, 0);
1422     float *vAsFloat = reinterpret_cast<float *>(v.data());
1423 
1424     vAsFloat[1] = 1.0f;
1425     vAsFloat[3] = 1.0f;
1426 
1427     glBufferData(GL_UNIFORM_BUFFER, kDataSize, v.data(), GL_STATIC_DRAW);
1428     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
1429     glUniformBlockBinding(program, uniformBufferIndex, 0);
1430     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1431     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1432 }
1433 
1434 // Block instance names can be reserved names in GLSL, as long as they're not reserved in GLSL ES.
TEST_P(UniformBufferTest,UniformBlockInstanceReservedOpenGLName)1435 TEST_P(UniformBufferTest, UniformBlockInstanceReservedOpenGLName)
1436 {
1437     constexpr char kFS[] =
1438         "#version 300 es\n"
1439         "precision highp float;\n"
1440         "out vec4 my_FragColor;\n"
1441         "layout(std140) uniform dmat2 { vec4 color; } buffer;\n"
1442         "void main()\n"
1443         "{\n"
1444         "    my_FragColor = buffer.color;\n"
1445         "}\n";
1446 
1447     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
1448     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "dmat2");
1449 
1450     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
1451     const GLsizei kElementsPerVector = 4;
1452     const GLsizei kBytesPerElement   = 4;
1453     const GLsizei kDataSize          = kElementsPerVector * kBytesPerElement;
1454     std::vector<GLubyte> v(kDataSize, 0);
1455     float *vAsFloat = reinterpret_cast<float *>(v.data());
1456 
1457     vAsFloat[1] = 1.0f;
1458     vAsFloat[3] = 1.0f;
1459 
1460     glBufferData(GL_UNIFORM_BUFFER, kDataSize, v.data(), GL_STATIC_DRAW);
1461     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
1462     glUniformBlockBinding(program, uniformBufferIndex, 0);
1463     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1464     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1465 }
1466 
1467 // Test that uniform block instance with nested structs that contain vec3s inside is handled
1468 // correctly. This is meant to test that HLSL structure padding to implement std140 layout works
1469 // together with uniform blocks.
TEST_P(UniformBufferTest,Std140UniformBlockInstanceWithNestedStructsContainingVec3s)1470 TEST_P(UniformBufferTest, Std140UniformBlockInstanceWithNestedStructsContainingVec3s)
1471 {
1472     // Got incorrect test result on non-NVIDIA Android - the alpha channel was not set correctly
1473     // from the second vector, possibly the platform doesn't implement std140 packing right?
1474     // http://anglebug.com/42260937
1475     ANGLE_SKIP_TEST_IF(IsAndroid() && !IsNVIDIA());
1476 
1477     constexpr char kFS[] =
1478         R"(#version 300 es
1479 
1480         precision highp float;
1481         out vec4 my_FragColor;
1482 
1483         struct Sinner {
1484           vec3 v;
1485         };
1486 
1487         struct S {
1488             Sinner s1;
1489             Sinner s2;
1490         };
1491 
1492         layout(std140) uniform structBuffer { S s; } buffer;
1493 
1494         void accessStruct(S s)
1495         {
1496             my_FragColor = vec4(s.s1.v.xy, s.s2.v.xy);
1497         }
1498 
1499         void main()
1500         {
1501             accessStruct(buffer.s);
1502         })";
1503 
1504     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
1505     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "structBuffer");
1506 
1507     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
1508     const GLsizei kVectorsPerBlock         = 2;
1509     const GLsizei kElementsPerPaddedVector = 4;
1510     const GLsizei kBytesPerElement         = 4;
1511     const GLsizei kDataSize = kVectorsPerBlock * kElementsPerPaddedVector * kBytesPerElement;
1512     std::vector<GLubyte> v(kDataSize, 0);
1513     float *vAsFloat = reinterpret_cast<float *>(v.data());
1514 
1515     // Set second value in each vec3.
1516     vAsFloat[1u]      = 1.0f;
1517     vAsFloat[4u + 1u] = 1.0f;
1518 
1519     glBufferData(GL_UNIFORM_BUFFER, kDataSize, v.data(), GL_STATIC_DRAW);
1520     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
1521     glUniformBlockBinding(program, uniformBufferIndex, 0);
1522     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1523     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1524 }
1525 
1526 // Tests the detaching shaders from the program and using uniform blocks works.
1527 // This covers a bug in ANGLE's D3D back-end.
TEST_P(UniformBufferTest,DetachShaders)1528 TEST_P(UniformBufferTest, DetachShaders)
1529 {
1530     GLuint vertexShader = CompileShader(GL_VERTEX_SHADER, essl3_shaders::vs::Simple());
1531     ASSERT_NE(0u, vertexShader);
1532     GLuint kFS = CompileShader(GL_FRAGMENT_SHADER, mkFS);
1533     ASSERT_NE(0u, kFS);
1534 
1535     GLuint program = glCreateProgram();
1536     glAttachShader(program, vertexShader);
1537     glAttachShader(program, kFS);
1538 
1539     ASSERT_TRUE(LinkAttachedProgram(program));
1540 
1541     glDetachShader(program, vertexShader);
1542     glDetachShader(program, kFS);
1543     glDeleteShader(vertexShader);
1544     glDeleteShader(kFS);
1545 
1546     glClear(GL_COLOR_BUFFER_BIT);
1547     float floatData[4] = {0.5f, 0.75f, 0.25f, 1.0f};
1548 
1549     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
1550     glBufferData(GL_UNIFORM_BUFFER, sizeof(float) * 4, floatData, GL_STATIC_DRAW);
1551 
1552     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
1553 
1554     GLint uniformBufferIndex = glGetUniformBlockIndex(mProgram, "uni");
1555     ASSERT_NE(uniformBufferIndex, -1);
1556 
1557     glUniformBlockBinding(program, uniformBufferIndex, 0);
1558     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1559 
1560     ASSERT_GL_NO_ERROR();
1561     EXPECT_PIXEL_NEAR(0, 0, 128, 191, 64, 255, 1);
1562 
1563     glDeleteProgram(program);
1564 }
1565 
1566 // Test a uniform block where the whole block is set as row-major.
TEST_P(UniformBufferTest,Std140UniformBlockWithRowMajorQualifier)1567 TEST_P(UniformBufferTest, Std140UniformBlockWithRowMajorQualifier)
1568 {
1569     // AMD OpenGL driver doesn't seem to apply the row-major qualifier right.
1570     // http://anglebug.com/40096480
1571     ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL() && !IsMac());
1572 
1573     constexpr char kFS[] =
1574         R"(#version 300 es
1575 
1576         precision highp float;
1577         out vec4 my_FragColor;
1578 
1579         layout(std140, row_major) uniform matrixBuffer
1580         {
1581             mat2 m;
1582         } buffer;
1583 
1584         void main()
1585         {
1586             // Vector constructor accesses elements in column-major order.
1587             my_FragColor = vec4(buffer.m);
1588         })";
1589 
1590     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
1591     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "matrixBuffer");
1592 
1593     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
1594     const GLsizei kElementsPerMatrix = 8;  // Each mat2 row gets padded into a vec4.
1595     const GLsizei kBytesPerElement   = 4;
1596     const GLsizei kDataSize          = kElementsPerMatrix * kBytesPerElement;
1597     std::vector<GLubyte> v(kDataSize, 0);
1598     float *vAsFloat = reinterpret_cast<float *>(v.data());
1599 
1600     vAsFloat[0u] = 1.0f;
1601     vAsFloat[1u] = 128.0f / 255.0f;
1602     vAsFloat[4u] = 64.0f / 255.0f;
1603     vAsFloat[5u] = 32.0f / 255.0f;
1604 
1605     glBufferData(GL_UNIFORM_BUFFER, kDataSize, v.data(), GL_STATIC_DRAW);
1606     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
1607     glUniformBlockBinding(program, uniformBufferIndex, 0);
1608     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1609     ASSERT_GL_NO_ERROR();
1610     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 64, 128, 32), 5);
1611 }
1612 
1613 // Test a uniform block where an individual matrix field is set as row-major whereas the whole block
1614 // is set as column-major.
TEST_P(UniformBufferTest,Std140UniformBlockWithPerMemberRowMajorQualifier)1615 TEST_P(UniformBufferTest, Std140UniformBlockWithPerMemberRowMajorQualifier)
1616 {
1617     // AMD OpenGL driver doesn't seem to apply the row-major qualifier right.
1618     // http://anglebug.com/40096480
1619     ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL() && !IsMac());
1620 
1621     constexpr char kFS[] =
1622         R"(#version 300 es
1623 
1624         precision highp float;
1625         out vec4 my_FragColor;
1626 
1627         layout(std140, column_major) uniform matrixBuffer
1628         {
1629             layout(row_major) mat2 m;
1630         } buffer;
1631 
1632         void main()
1633         {
1634             // Vector constructor accesses elements in column-major order.
1635             my_FragColor = vec4(buffer.m);
1636         })";
1637 
1638     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
1639     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "matrixBuffer");
1640 
1641     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
1642     const GLsizei kElementsPerMatrix = 8;  // Each mat2 row gets padded into a vec4.
1643     const GLsizei kBytesPerElement   = 4;
1644     const GLsizei kDataSize          = kElementsPerMatrix * kBytesPerElement;
1645     std::vector<GLubyte> v(kDataSize, 0);
1646     float *vAsFloat = reinterpret_cast<float *>(v.data());
1647 
1648     vAsFloat[0u] = 1.0f;
1649     vAsFloat[1u] = 128.0f / 255.0f;
1650     vAsFloat[4u] = 64.0f / 255.0f;
1651     vAsFloat[5u] = 32.0f / 255.0f;
1652 
1653     glBufferData(GL_UNIFORM_BUFFER, kDataSize, v.data(), GL_STATIC_DRAW);
1654     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
1655     glUniformBlockBinding(program, uniformBufferIndex, 0);
1656     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1657     ASSERT_GL_NO_ERROR();
1658     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 64, 128, 32), 5);
1659 }
1660 
1661 // Test a uniform block where an individual matrix field is set as column-major whereas the whole
1662 // block is set as row-major.
TEST_P(UniformBufferTest,Std140UniformBlockWithPerMemberColumnMajorQualifier)1663 TEST_P(UniformBufferTest, Std140UniformBlockWithPerMemberColumnMajorQualifier)
1664 {
1665     constexpr char kFS[] =
1666         R"(#version 300 es
1667 
1668         precision highp float;
1669         out vec4 my_FragColor;
1670 
1671         layout(std140, row_major) uniform matrixBuffer
1672         {
1673             // 2 columns, 3 rows.
1674             layout(column_major) mat2x3 m;
1675         } buffer;
1676 
1677         void main()
1678         {
1679             // Vector constructor accesses elements in column-major order.
1680             my_FragColor = vec4(buffer.m);
1681         })";
1682 
1683     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
1684     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "matrixBuffer");
1685 
1686     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
1687     const GLsizei kElementsPerMatrix = 8;  // Each mat2x3 column gets padded into a vec4.
1688     const GLsizei kBytesPerElement   = 4;
1689     const GLsizei kDataSize          = kElementsPerMatrix * kBytesPerElement;
1690     std::vector<GLubyte> v(kDataSize, 0);
1691     float *vAsFloat = reinterpret_cast<float *>(v.data());
1692 
1693     vAsFloat[0u] = 1.0f;
1694     vAsFloat[1u] = 192.0f / 255.0f;
1695     vAsFloat[2u] = 128.0f / 255.0f;
1696     vAsFloat[4u] = 96.0f / 255.0f;
1697     vAsFloat[5u] = 64.0f / 255.0f;
1698     vAsFloat[6u] = 32.0f / 255.0f;
1699 
1700     glBufferData(GL_UNIFORM_BUFFER, kDataSize, v.data(), GL_STATIC_DRAW);
1701     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
1702     glUniformBlockBinding(program, uniformBufferIndex, 0);
1703     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1704     ASSERT_GL_NO_ERROR();
1705     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 192, 128, 96), 5);
1706 }
1707 
1708 // Test a uniform block where a struct field is set as row-major.
TEST_P(UniformBufferTest,Std140UniformBlockWithRowMajorQualifierOnStruct)1709 TEST_P(UniformBufferTest, Std140UniformBlockWithRowMajorQualifierOnStruct)
1710 {
1711     // AMD OpenGL driver doesn't seem to apply the row-major qualifier right.
1712     // http://anglebug.com/40096480
1713     ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL() && !IsMac());
1714 
1715     constexpr char kFS[] =
1716         R"(#version 300 es
1717 
1718         precision highp float;
1719         out vec4 my_FragColor;
1720 
1721         struct S
1722         {
1723             mat2 m;
1724         };
1725 
1726         layout(std140) uniform matrixBuffer
1727         {
1728             layout(row_major) S s;
1729         } buffer;
1730 
1731         void main()
1732         {
1733             // Vector constructor accesses elements in column-major order.
1734             my_FragColor = vec4(buffer.s.m);
1735         })";
1736 
1737     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
1738     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "matrixBuffer");
1739 
1740     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
1741     const GLsizei kElementsPerMatrix = 8;  // Each mat2 row gets padded into a vec4.
1742     const GLsizei kBytesPerElement   = 4;
1743     const GLsizei kDataSize          = kElementsPerMatrix * kBytesPerElement;
1744     std::vector<GLubyte> v(kDataSize, 0);
1745     float *vAsFloat = reinterpret_cast<float *>(v.data());
1746 
1747     vAsFloat[0u] = 1.0f;
1748     vAsFloat[1u] = 128.0f / 255.0f;
1749     vAsFloat[4u] = 64.0f / 255.0f;
1750     vAsFloat[5u] = 32.0f / 255.0f;
1751 
1752     glBufferData(GL_UNIFORM_BUFFER, kDataSize, v.data(), GL_STATIC_DRAW);
1753     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
1754     glUniformBlockBinding(program, uniformBufferIndex, 0);
1755     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1756     ASSERT_GL_NO_ERROR();
1757     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 64, 128, 32), 5);
1758 }
1759 
1760 // Regression test for a dirty bit bug in ANGLE. See http://crbug.com/792966
TEST_P(UniformBufferTest,SimpleBindingChange)1761 TEST_P(UniformBufferTest, SimpleBindingChange)
1762 {
1763     constexpr char kFragmentShader[] = R"(#version 300 es
1764 precision mediump float;
1765 
1766 layout (std140) uniform color_ubo
1767 {
1768   vec4 color;
1769 };
1770 
1771 out vec4 fragColor;
1772 void main()
1773 {
1774   fragColor = color;
1775 })";
1776 
1777     // http://anglebug.com/40096481
1778     ANGLE_SKIP_TEST_IF(IsMac() && IsNVIDIA() && IsDesktopOpenGL());
1779 
1780     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFragmentShader);
1781 
1782     glBindAttribLocation(program, 0, essl3_shaders::PositionAttrib());
1783     glUseProgram(program);
1784     GLint uboIndex = glGetUniformBlockIndex(program, "color_ubo");
1785 
1786     std::array<GLfloat, 12> vertices{{-1, -1, 0, 1, -1, 0, -1, 1, 0, 1, 1, 0}};
1787     GLBuffer vertexBuf;
1788     glBindBuffer(GL_ARRAY_BUFFER, vertexBuf);
1789     glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), vertices.data(),
1790                  GL_STATIC_DRAW);
1791     glEnableVertexAttribArray(0);
1792     glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
1793 
1794     std::array<GLshort, 12> indexData = {{0, 1, 2, 2, 1, 3, 0, 1, 2, 2, 1, 3}};
1795 
1796     GLBuffer indexBuf;
1797     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf);
1798     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexData.size() * sizeof(GLshort), indexData.data(),
1799                  GL_STATIC_DRAW);
1800 
1801     // Bind a first buffer with red.
1802     GLBuffer uboBuf1;
1803     glBindBufferBase(GL_UNIFORM_BUFFER, 0, uboBuf1);
1804     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatRed, GL_STATIC_DRAW);
1805     glUniformBlockBinding(program, uboIndex, 0);
1806 
1807     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
1808 
1809     // Bind a second buffer with green, updating the buffer binding.
1810     GLBuffer uboBuf2;
1811     glBindBufferBase(GL_UNIFORM_BUFFER, 1, uboBuf2);
1812     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatGreen, GL_STATIC_DRAW);
1813     glUniformBlockBinding(program, uboIndex, 1);
1814 
1815     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, reinterpret_cast<const GLvoid *>(12));
1816 
1817     // Verify we get the second buffer.
1818     ASSERT_GL_NO_ERROR();
1819     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1820 }
1821 
1822 // Regression test for a dirty bit bug in ANGLE. Same as above but for the indexed bindings.
TEST_P(UniformBufferTest,SimpleBufferChange)1823 TEST_P(UniformBufferTest, SimpleBufferChange)
1824 {
1825     constexpr char kFragmentShader[] = R"(#version 300 es
1826 precision mediump float;
1827 
1828 layout (std140) uniform color_ubo
1829 {
1830   vec4 color;
1831 };
1832 
1833 out vec4 fragColor;
1834 void main()
1835 {
1836   fragColor = color;
1837 })";
1838 
1839     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFragmentShader);
1840 
1841     glBindAttribLocation(program, 0, essl3_shaders::PositionAttrib());
1842     glUseProgram(program);
1843     GLint uboIndex = glGetUniformBlockIndex(program, "color_ubo");
1844 
1845     std::array<GLfloat, 12> vertices{{-1, -1, 0, 1, -1, 0, -1, 1, 0, 1, 1, 0}};
1846     GLBuffer vertexBuf;
1847     glBindBuffer(GL_ARRAY_BUFFER, vertexBuf);
1848     glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), vertices.data(),
1849                  GL_STATIC_DRAW);
1850     glEnableVertexAttribArray(0);
1851     glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
1852 
1853     std::array<GLshort, 12> indexData = {{0, 1, 2, 2, 1, 3, 0, 1, 2, 2, 1, 3}};
1854 
1855     GLBuffer indexBuf;
1856     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf);
1857     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexData.size() * sizeof(GLshort), indexData.data(),
1858                  GL_STATIC_DRAW);
1859 
1860     // Bind a first buffer with red.
1861     GLBuffer uboBuf1;
1862     glBindBufferBase(GL_UNIFORM_BUFFER, 0, uboBuf1);
1863     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatRed, GL_STATIC_DRAW);
1864     glUniformBlockBinding(program, uboIndex, 0);
1865 
1866     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
1867 
1868     // Bind a second buffer to the same binding point (0). This should set to draw green.
1869     GLBuffer uboBuf2;
1870     glBindBufferBase(GL_UNIFORM_BUFFER, 0, uboBuf2);
1871     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatGreen, GL_STATIC_DRAW);
1872 
1873     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, reinterpret_cast<const GLvoid *>(12));
1874 
1875     ASSERT_GL_NO_ERROR();
1876     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1877 }
1878 
1879 // Tests a bug in the D3D11 back-end where re-creating the buffer storage should trigger a state
1880 // update in the State Manager class.
TEST_P(UniformBufferTest,DependentBufferChange)1881 TEST_P(UniformBufferTest, DependentBufferChange)
1882 {
1883     constexpr char kFragmentShader[] = R"(#version 300 es
1884 precision mediump float;
1885 
1886 layout (std140) uniform color_ubo
1887 {
1888   vec4 color;
1889 };
1890 
1891 out vec4 fragColor;
1892 void main()
1893 {
1894   fragColor = color;
1895 })";
1896 
1897     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFragmentShader);
1898 
1899     glBindAttribLocation(program, 0, essl3_shaders::PositionAttrib());
1900     glUseProgram(program);
1901     GLint uboIndex = glGetUniformBlockIndex(program, "color_ubo");
1902 
1903     std::array<GLfloat, 12> vertices{{-1, -1, 0, 1, -1, 0, -1, 1, 0, 1, 1, 0}};
1904     GLBuffer vertexBuf;
1905     glBindBuffer(GL_ARRAY_BUFFER, vertexBuf);
1906     glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), vertices.data(),
1907                  GL_STATIC_DRAW);
1908     glEnableVertexAttribArray(0);
1909     glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
1910 
1911     std::array<GLshort, 6> indexData = {{0, 1, 2, 2, 1, 3}};
1912 
1913     GLBuffer indexBuf;
1914     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf);
1915     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexData.size() * sizeof(GLshort), indexData.data(),
1916                  GL_STATIC_DRAW);
1917 
1918     GLBuffer ubo;
1919     glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo);
1920     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatRed, GL_STATIC_DRAW);
1921     glUniformBlockBinding(program, uboIndex, 0);
1922 
1923     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0);
1924     ASSERT_GL_NO_ERROR();
1925     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1926 
1927     // Resize the buffer - triggers a re-allocation in the D3D11 back-end.
1928     std::vector<GLColor32F> bigData(128, kFloatGreen);
1929     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F) * bigData.size(), bigData.data(),
1930                  GL_STATIC_DRAW);
1931 
1932     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0);
1933     ASSERT_GL_NO_ERROR();
1934     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1935 }
1936 
1937 // Recreate WebGL conformance test conformance2/uniforms/large-uniform-buffers.html to test
1938 // regression in http://anglebug.com/42262055
TEST_P(UniformBufferTest,SizeOverMaxBlockSize)1939 TEST_P(UniformBufferTest, SizeOverMaxBlockSize)
1940 {
1941     constexpr char kFragmentShader[] = R"(#version 300 es
1942 precision mediump float;
1943 
1944 layout (std140) uniform color_ubo
1945 {
1946   vec4 color;
1947 };
1948 
1949 out vec4 fragColor;
1950 void main()
1951 {
1952   fragColor = color;
1953 })";
1954 
1955     // Test crashes on Windows AMD OpenGL
1956     ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsOpenGL());
1957     // http://anglebug.com/42263922
1958     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
1959 
1960     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFragmentShader);
1961 
1962     glBindAttribLocation(program, 0, essl3_shaders::PositionAttrib());
1963     glUseProgram(program);
1964     GLint uboIndex = glGetUniformBlockIndex(program, "color_ubo");
1965 
1966     std::array<GLfloat, 12> vertices{{-1, -1, 0, 1, -1, 0, -1, 1, 0, 1, 1, 0}};
1967     GLBuffer vertexBuf;
1968     glBindBuffer(GL_ARRAY_BUFFER, vertexBuf);
1969     glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), vertices.data(),
1970                  GL_STATIC_DRAW);
1971     glEnableVertexAttribArray(0);
1972     glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
1973 
1974     std::array<GLshort, 6> indexData = {{0, 1, 2, 2, 1, 3}};
1975 
1976     GLBuffer indexBuf;
1977     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf);
1978     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexData.size() * sizeof(GLshort), indexData.data(),
1979                  GL_STATIC_DRAW);
1980 
1981     GLint uboDataSize = 0;
1982     glGetActiveUniformBlockiv(program, uboIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &uboDataSize);
1983     EXPECT_NE(uboDataSize, 0);  // uniform block data size invalid
1984 
1985     GLint64 maxUniformBlockSize;
1986     glGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize);
1987 
1988     GLBuffer uboBuf;
1989     std::vector<GLfloat> uboData;
1990     uboData.resize(maxUniformBlockSize * 2);  // underlying data is twice the max block size
1991 
1992     GLint offs0 = 0;
1993 
1994     // Red
1995     uboData[offs0 + 0] = 1;
1996     uboData[offs0 + 1] = 0;
1997     uboData[offs0 + 2] = 0;
1998     uboData[offs0 + 3] = 1;
1999 
2000     GLint offs1     = maxUniformBlockSize;
2001     GLint alignment = 0;
2002     glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &alignment);
2003     EXPECT_EQ(offs1 % alignment, 0);
2004 
2005     // Green
2006     uboData[offs1 + 0] = 0;
2007     uboData[offs1 + 1] = 1;
2008     uboData[offs1 + 2] = 0;
2009     uboData[offs1 + 3] = 1;
2010 
2011     glUniformBlockBinding(program, uboIndex, 0);
2012     glBindBufferBase(GL_UNIFORM_BUFFER, 0, uboBuf);
2013     glBufferData(GL_UNIFORM_BUFFER, uboData.size() * sizeof(GLfloat), uboData.data(),
2014                  GL_STATIC_DRAW);
2015     ASSERT_GL_NO_ERROR();  // No errors from setup
2016 
2017     // Draw lower triangle - should be red
2018     glBindBufferRange(GL_UNIFORM_BUFFER, 0, uboBuf, offs0 * sizeof(float), 4 * sizeof(float));
2019     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0);
2020     ASSERT_GL_NO_ERROR();  // No errors from draw
2021 
2022     // Draw upper triangle - should be green
2023     glBindBufferRange(GL_UNIFORM_BUFFER, 0, uboBuf, offs1 * sizeof(float), 4 * sizeof(float));
2024     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT,
2025                    reinterpret_cast<void *>(3 * sizeof(GLshort)));
2026     ASSERT_GL_NO_ERROR();  // No errors from draw
2027 
2028     GLint width  = getWindowWidth();
2029     GLint height = getWindowHeight();
2030     // Lower left should be red
2031     EXPECT_PIXEL_COLOR_EQ(width / 2 - 5, height / 2 - 5, GLColor::red);
2032     // Top right should be green
2033     EXPECT_PIXEL_COLOR_EQ(width / 2 + 5, height / 2 + 5, GLColor::green);
2034 }
2035 
2036 // Test a uniform block where an array of row-major matrices is dynamically indexed.
TEST_P(UniformBufferTest,Std140UniformBlockWithDynamicallyIndexedRowMajorArray)2037 TEST_P(UniformBufferTest, Std140UniformBlockWithDynamicallyIndexedRowMajorArray)
2038 {
2039     // http://anglebug.com/42262481 , http://anglebug.com/40096480
2040     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL() && (IsIntel() || IsAMD()));
2041 
2042     constexpr char kFS[] =
2043         R"(#version 300 es
2044 
2045         precision highp float;
2046         out vec4 my_FragColor;
2047 
2048         uniform int u_zero;
2049 
2050         layout(std140, row_major) uniform matrixBuffer {
2051             mat4 u_mats[1];
2052         };
2053 
2054         void main() {
2055             float f = u_mats[u_zero + 0][2][1];
2056             my_FragColor = vec4(1.0 - f, f, 0.0, 1.0);
2057         })";
2058 
2059     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
2060     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "matrixBuffer");
2061 
2062     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
2063     const GLsizei kElementsPerMatrix = 16;  // Each mat2 row gets padded into a vec4.
2064     const GLsizei kBytesPerElement   = 4;
2065     const GLsizei kDataSize          = kElementsPerMatrix * kBytesPerElement;
2066     std::vector<GLubyte> v(kDataSize, 0);
2067     float *vAsFloat = reinterpret_cast<float *>(v.data());
2068     // Write out this initializer to make it clearer what the matrix contains.
2069     float matrixData[kElementsPerMatrix] = {
2070         // clang-format off
2071         0.0f, 0.0f, 0.0f, 0.0f,
2072         0.0f, 0.0f, 1.0f, 0.0f,
2073         0.0f, 0.0f, 0.0f, 0.0f,
2074         0.0f, 0.0f, 0.0f, 0.0f,
2075         // clang-format on
2076     };
2077     for (int ii = 0; ii < kElementsPerMatrix; ++ii)
2078     {
2079         vAsFloat[ii] = matrixData[ii];
2080     }
2081     glBufferData(GL_UNIFORM_BUFFER, kDataSize, v.data(), GL_STATIC_DRAW);
2082     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
2083     glUniformBlockBinding(program, uniformBufferIndex, 0);
2084     GLint indexLoc = glGetUniformLocation(program, "u_zero");
2085     glUseProgram(program);
2086     glUniform1i(indexLoc, 0);
2087     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2088     ASSERT_GL_NO_ERROR();
2089     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0, 255, 0, 255), 5);
2090 }
2091 
2092 // Test with many uniform buffers work as expected.
TEST_P(UniformBufferTest,ManyBlocks)2093 TEST_P(UniformBufferTest, ManyBlocks)
2094 {
2095     // http://anglebug.com/42263608
2096     ANGLE_SKIP_TEST_IF(IsD3D11());
2097 
2098     constexpr char kFS[] =
2099         R"(#version 300 es
2100 
2101         precision highp float;
2102         out vec4 my_FragColor;
2103 
2104         layout(std140) uniform uboBlock { vec4 color; } blocks[12];
2105 
2106         void main()
2107         {
2108             vec4 color = vec4(0, 0, 0, 1);
2109             color += blocks[0].color;
2110             color += blocks[1].color;
2111             color += blocks[2].color;
2112             color += blocks[3].color;
2113             color += blocks[4].color;
2114             color += blocks[5].color;
2115             color += blocks[6].color;
2116             color += blocks[7].color;
2117             color += blocks[8].color;
2118             color += blocks[9].color;
2119             color += blocks[10].color;
2120             color += blocks[11].color;
2121             my_FragColor = vec4(color.rgb, 1.0);
2122         })";
2123 
2124     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
2125     GLBuffer buffers[12];
2126     GLint bufferIndex[12];
2127     bufferIndex[0]  = glGetUniformBlockIndex(program, "uboBlock[0]");
2128     bufferIndex[1]  = glGetUniformBlockIndex(program, "uboBlock[1]");
2129     bufferIndex[2]  = glGetUniformBlockIndex(program, "uboBlock[2]");
2130     bufferIndex[3]  = glGetUniformBlockIndex(program, "uboBlock[3]");
2131     bufferIndex[4]  = glGetUniformBlockIndex(program, "uboBlock[4]");
2132     bufferIndex[5]  = glGetUniformBlockIndex(program, "uboBlock[5]");
2133     bufferIndex[6]  = glGetUniformBlockIndex(program, "uboBlock[6]");
2134     bufferIndex[7]  = glGetUniformBlockIndex(program, "uboBlock[7]");
2135     bufferIndex[8]  = glGetUniformBlockIndex(program, "uboBlock[8]");
2136     bufferIndex[9]  = glGetUniformBlockIndex(program, "uboBlock[9]");
2137     bufferIndex[10] = glGetUniformBlockIndex(program, "uboBlock[10]");
2138     bufferIndex[11] = glGetUniformBlockIndex(program, "uboBlock[11]");
2139 
2140     std::vector<GLubyte> v(16, 0);
2141     float *vAsFloat = reinterpret_cast<float *>(v.data());
2142 
2143     for (int i = 0; i < 12; ++i)
2144     {
2145         glBindBuffer(GL_UNIFORM_BUFFER, buffers[i]);
2146         vAsFloat[0] = (i + 1) / 255.0f;
2147         vAsFloat[1] = (i + 1) / 255.0f;
2148         vAsFloat[2] = (i + 1) / 255.0f;
2149         vAsFloat[3] = .0f;
2150 
2151         glBufferData(GL_UNIFORM_BUFFER, v.size(), v.data(), GL_STATIC_DRAW);
2152 
2153         glBindBufferBase(GL_UNIFORM_BUFFER, i, buffers[i]);
2154         glUniformBlockBinding(program, bufferIndex[i], i);
2155     }
2156 
2157     glViewport(0, 0, getWindowWidth() / 2, getWindowHeight());
2158     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2159 
2160     // Modify buffer[1]
2161     glBindBuffer(GL_UNIFORM_BUFFER, buffers[1]);
2162 
2163     vAsFloat[0] = 2 / 255.0f;
2164     vAsFloat[1] = 22 / 255.0f;  // green channel increased by 20
2165     vAsFloat[2] = 2 / 255.0f;
2166     vAsFloat[3] = .0f;
2167 
2168     glBufferData(GL_UNIFORM_BUFFER, v.size(), v.data(), GL_STATIC_DRAW);
2169 
2170     glViewport(getWindowWidth() / 2, 0, getWindowWidth() / 2, getWindowHeight());
2171     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2172 
2173     // First draw
2174     EXPECT_PIXEL_NEAR(0, 0, 78, 78, 78, 255, 2);
2175     // Second draw: green channel increased by 20
2176     EXPECT_PIXEL_NEAR(getWindowWidth() / 2, 0, 78, 98, 78, 255, 2);
2177 }
2178 
2179 // These suite cases test the uniform blocks with a large array member. Unlike other uniform
2180 // blocks that will be translated to cbuffer type on D3D backend, we will tranlate these
2181 // uniform blocks to StructuredBuffer for slow fxc compile performance issue with dynamic
2182 // uniform indexing, angleproject/3682.
2183 class UniformBlockWithOneLargeArrayMemberTest : public ANGLETest<>
2184 {
2185   protected:
UniformBlockWithOneLargeArrayMemberTest()2186     UniformBlockWithOneLargeArrayMemberTest()
2187     {
2188         setWindowWidth(128);
2189         setWindowHeight(128);
2190         setConfigRedBits(8);
2191         setConfigGreenBits(8);
2192         setConfigBlueBits(8);
2193         setConfigAlphaBits(8);
2194     }
2195 
testSetUp()2196     void testSetUp() override
2197     {
2198         glGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &mMaxUniformBlockSize);
2199         // Ensure that shader uniform block does not exceed MAX_UNIFORM_BLOCK_SIZE limit.
2200         if (mMaxUniformBlockSize >= 16384 && mMaxUniformBlockSize < 32768)
2201         {
2202             mArraySize1 = 128;
2203             mArraySize2 = 8;
2204             mDivisor1   = 128;
2205             mDivisor2   = 32;
2206             mDivisor3   = 16;
2207         }
2208         else if (mMaxUniformBlockSize >= 32768 && mMaxUniformBlockSize < 65536)
2209         {
2210             mArraySize1 = 256;
2211             mArraySize2 = 16;
2212             mDivisor1   = 64;
2213             mDivisor2   = 16;
2214             mDivisor3   = 8;
2215         }
2216         else
2217         {
2218             mArraySize1 = 512;
2219             mArraySize2 = 32;
2220             mDivisor1   = 32;
2221             mDivisor2   = 8;
2222             mDivisor3   = 4;
2223         }
2224 
2225         glGenBuffers(1, &mUniformBuffer);
2226         ASSERT_GL_NO_ERROR();
2227     }
2228 
testTearDown()2229     void testTearDown() override { glDeleteBuffers(1, &mUniformBuffer); }
2230 
generateArraySizeAndDivisorsDeclaration(std::ostringstream & out,bool hasArraySize2,bool hasDivisor2,bool hasDivisor3)2231     void generateArraySizeAndDivisorsDeclaration(std::ostringstream &out,
2232                                                  bool hasArraySize2,
2233                                                  bool hasDivisor2,
2234                                                  bool hasDivisor3)
2235     {
2236         if (hasArraySize2)
2237         {
2238             out << "const uint arraySize1 = " << mArraySize1 << "u;\n";
2239             out << "const uint arraySize2 = " << mArraySize2 << "u;\n";
2240         }
2241         else
2242         {
2243             out << "const uint arraySize = " << mArraySize1 << "u;\n";
2244         }
2245 
2246         if (hasDivisor2)
2247         {
2248             out << "const uint divisor1 = " << mDivisor1 << "u;\n";
2249             out << "const uint divisor2 = " << mDivisor2 << "u;\n";
2250         }
2251         else
2252         {
2253             out << "const uint divisor = " << mDivisor1 << "u;\n";
2254         }
2255         if (hasDivisor3)
2256         {
2257             out << "const uint divisor3 = " << mDivisor3 << "u;\n";
2258         }
2259     }
getArraySize()2260     GLuint getArraySize() { return mArraySize1; }
getArraySize2()2261     GLuint getArraySize2() { return mArraySize2; }
2262 
setArrayValues(std::vector<GLfloat> & floatData,GLuint beginIndex,GLuint endIndex,GLuint stride,GLuint firstElementOffset,GLuint firstEleVecCount,GLuint firstEleVecComponents,float x1,float y1,float z1,float w1,GLuint secondElementOffset=0,GLuint secondEleVecCount=0,GLuint secondEleVecComponents=0,float x2=0.0f,float y2=0.0f,float z2=0.0f,float w2=0.0f)2263     void setArrayValues(std::vector<GLfloat> &floatData,
2264                         GLuint beginIndex,
2265                         GLuint endIndex,
2266                         GLuint stride,
2267                         GLuint firstElementOffset,
2268                         GLuint firstEleVecCount,
2269                         GLuint firstEleVecComponents,
2270                         float x1,
2271                         float y1,
2272                         float z1,
2273                         float w1,
2274                         GLuint secondElementOffset    = 0,
2275                         GLuint secondEleVecCount      = 0,
2276                         GLuint secondEleVecComponents = 0,
2277                         float x2                      = 0.0f,
2278                         float y2                      = 0.0f,
2279                         float z2                      = 0.0f,
2280                         float w2                      = 0.0f)
2281     {
2282         for (GLuint i = beginIndex; i < endIndex; i++)
2283         {
2284             for (GLuint j = 0; j < firstEleVecCount; j++)
2285             {
2286                 if (firstEleVecComponents > 3)
2287                 {
2288                     floatData[i * stride + firstElementOffset + 4 * j + 3] = w1;
2289                 }
2290                 if (firstEleVecComponents > 2)
2291                 {
2292                     floatData[i * stride + firstElementOffset + 4 * j + 2] = z1;
2293                 }
2294                 if (firstEleVecComponents > 1)
2295                 {
2296                     floatData[i * stride + firstElementOffset + 4 * j + 1] = y1;
2297                 }
2298                 floatData[i * stride + firstElementOffset + 4 * j] = x1;
2299             }
2300 
2301             for (GLuint k = 0; k < secondEleVecCount; k++)
2302             {
2303                 if (secondEleVecComponents > 3)
2304                 {
2305                     floatData[i * stride + secondElementOffset + 4 * k + 3] = w2;
2306                 }
2307                 if (secondEleVecComponents > 2)
2308                 {
2309                     floatData[i * stride + secondElementOffset + 4 * k + 2] = z2;
2310                 }
2311                 if (secondEleVecComponents > 1)
2312                 {
2313                     floatData[i * stride + secondElementOffset + 4 * k + 1] = y2;
2314                 }
2315                 floatData[i * stride + secondElementOffset + 4 * k] = x2;
2316             }
2317         }
2318     }
2319 
checkResults(const GLColor & firstQuarter,const GLColor & secondQuarter,const GLColor & thirdQuarter,const GLColor & fourthQuarter)2320     void checkResults(const GLColor &firstQuarter,
2321                       const GLColor &secondQuarter,
2322                       const GLColor &thirdQuarter,
2323                       const GLColor &fourthQuarter)
2324     {
2325         for (GLuint i = 0; i < kPositionCount; i++)
2326         {
2327             if (positionToTest[i][1] >= 0 && positionToTest[i][1] < 32)
2328             {
2329                 EXPECT_PIXEL_COLOR_EQ(positionToTest[i][0], positionToTest[i][1], firstQuarter);
2330             }
2331             else if (positionToTest[i][1] >= 32 && positionToTest[i][1] < 64)
2332             {
2333                 EXPECT_PIXEL_COLOR_EQ(positionToTest[i][0], positionToTest[i][1], secondQuarter);
2334             }
2335             else if (positionToTest[i][1] >= 64 && positionToTest[i][1] < 96)
2336             {
2337                 EXPECT_PIXEL_COLOR_EQ(positionToTest[i][0], positionToTest[i][1], thirdQuarter);
2338             }
2339             else
2340             {
2341                 EXPECT_PIXEL_COLOR_EQ(positionToTest[i][0], positionToTest[i][1], fourthQuarter);
2342             }
2343         }
2344     }
2345 
2346     GLuint mUniformBuffer;
2347     GLint64 mMaxUniformBlockSize;
2348     GLuint mArraySize1;
2349     GLuint mArraySize2;
2350     GLuint mDivisor1;
2351     GLuint mDivisor2;
2352     GLuint mDivisor3;
2353 
2354     static constexpr GLuint kVectorPerMat                           = 4;
2355     static constexpr GLuint kFloatPerVector                         = 4;
2356     static constexpr GLuint kPositionCount                          = 12;
2357     static constexpr unsigned int positionToTest[kPositionCount][2] = {
2358         {0, 0},   {75, 0},  {98, 13}, {31, 31}, {0, 32},   {65, 33},
2359         {23, 54}, {63, 63}, {0, 64},  {43, 86}, {53, 100}, {127, 127}};
2360 };
2361 
2362 // Test uniform block whose member is structure type, which contains a mat4 member.
TEST_P(UniformBlockWithOneLargeArrayMemberTest,MemberTypeIsStruct)2363 TEST_P(UniformBlockWithOneLargeArrayMemberTest, MemberTypeIsStruct)
2364 {
2365     std::ostringstream stream;
2366     generateArraySizeAndDivisorsDeclaration(stream, false, true, false);
2367     const std::string &kFS =
2368         "#version 300 es\n"
2369         "precision highp float;\n" +
2370         stream.str() +
2371         "out vec4 my_FragColor;\n"
2372         "struct S { mat4 color;};\n"
2373         "layout(std140) uniform buffer { S s[arraySize]; };\n"
2374         "void main()\n"
2375         "{\n"
2376         "    uvec2 coord = uvec2(floor(gl_FragCoord.xy));\n"
2377         "    uint index = coord.x +  coord.y * 128u;\n"
2378         "    uint index_x = index / divisor1;\n"
2379         "    uint index_y = (index % divisor1) / divisor2;\n"
2380         "    my_FragColor = s[index_x].color[index_y];\n"
2381         "}\n";
2382 
2383     GLint blockSize;
2384     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS.c_str());
2385     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "buffer");
2386     glGetActiveUniformBlockiv(program, uniformBufferIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
2387 
2388     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
2389     glBufferData(GL_UNIFORM_BUFFER, blockSize, nullptr, GL_STATIC_DRAW);
2390 
2391     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
2392     glUniformBlockBinding(program, uniformBufferIndex, 0);
2393 
2394     const GLuint arraySize  = getArraySize();
2395     const GLuint floatCount = arraySize * kVectorPerMat * kFloatPerVector;
2396     std::vector<GLfloat> floatData(floatCount, 0.0f);
2397 
2398     setArrayValues(floatData, 0, arraySize, 16, 0, 4, 4, 0.0f, 0.0f, 1.0f, 1.0f);
2399     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData.data());
2400     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2401     checkResults(GLColor::blue, GLColor::blue, GLColor::blue, GLColor::blue);
2402 
2403     setArrayValues(floatData, 0, arraySize, 16, 0, 4, 4, 0.0f, 1.0f, 0.0f, 1.0f);
2404     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData.data());
2405     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2406     checkResults(GLColor::green, GLColor::green, GLColor::green, GLColor::green);
2407 
2408     setArrayValues(floatData, arraySize / 4, arraySize / 2, 16, 0, 4, 4, 1.0f, 0.0f, 0.0f, 1.0f);
2409     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData.data());
2410     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2411     checkResults(GLColor::green, GLColor::red, GLColor::green, GLColor::green);
2412 }
2413 
2414 // Test instanced uniform block whose member is structure type, which contains a mat4 member.
TEST_P(UniformBlockWithOneLargeArrayMemberTest,MemberTypeIsStructAndInstanced)2415 TEST_P(UniformBlockWithOneLargeArrayMemberTest, MemberTypeIsStructAndInstanced)
2416 {
2417     std::ostringstream stream;
2418     generateArraySizeAndDivisorsDeclaration(stream, false, true, false);
2419     const std::string &kFS =
2420         "#version 300 es\n"
2421         "precision highp float;\n" +
2422         stream.str() +
2423         "out vec4 my_FragColor;\n"
2424         "struct S { mat4 color;};\n"
2425         "layout(std140) uniform buffer { S s[arraySize]; } instance;\n"
2426         "void main()\n"
2427         "{\n"
2428         "    uvec2 coord = uvec2(floor(gl_FragCoord.xy));\n"
2429         "    uint index = coord.x +  coord.y * 128u;\n"
2430         "    uint index_x = index / divisor1;\n"
2431         "    uint index_y = (index % divisor1) / divisor2;\n"
2432         "    my_FragColor = instance.s[index_x].color[index_y];\n"
2433         "}\n";
2434 
2435     GLint blockSize;
2436     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS.c_str());
2437     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "buffer");
2438     glGetActiveUniformBlockiv(program, uniformBufferIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
2439 
2440     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
2441     glBufferData(GL_UNIFORM_BUFFER, blockSize, nullptr, GL_STATIC_DRAW);
2442 
2443     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
2444     glUniformBlockBinding(program, uniformBufferIndex, 0);
2445 
2446     const GLuint arraySize  = getArraySize();
2447     const GLuint floatCount = arraySize * kVectorPerMat * kFloatPerVector;
2448     std::vector<GLfloat> floatData(floatCount, 0.0f);
2449 
2450     setArrayValues(floatData, 0, arraySize, 16, 0, 4, 4, 0.0f, 0.0f, 1.0f, 1.0f);
2451     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData.data());
2452     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2453     checkResults(GLColor::blue, GLColor::blue, GLColor::blue, GLColor::blue);
2454 
2455     setArrayValues(floatData, 0, arraySize, 16, 0, 4, 4, 0.0f, 1.0f, 0.0f, 1.0f);
2456     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData.data());
2457     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2458     checkResults(GLColor::green, GLColor::green, GLColor::green, GLColor::green);
2459 
2460     setArrayValues(floatData, arraySize / 4, arraySize / 2, 16, 0, 4, 4, 1.0f, 0.0f, 0.0f, 1.0f);
2461     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData.data());
2462     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2463     checkResults(GLColor::green, GLColor::red, GLColor::green, GLColor::green);
2464 }
2465 
2466 // Test instanced uniform block array whose member is structure type, which contains a mat4 member.
TEST_P(UniformBlockWithOneLargeArrayMemberTest,MemberTypeIsStructAndInstancedArray)2467 TEST_P(UniformBlockWithOneLargeArrayMemberTest, MemberTypeIsStructAndInstancedArray)
2468 {
2469     std::ostringstream stream;
2470     generateArraySizeAndDivisorsDeclaration(stream, false, true, false);
2471     const std::string &kFS =
2472         "#version 300 es\n"
2473         "precision highp float;\n" +
2474         stream.str() +
2475         "out vec4 my_FragColor;\n"
2476         "struct S { mat4 color;};\n"
2477         "layout(std140) uniform buffer { S s[arraySize]; } instance[2];\n"
2478         "void main()\n"
2479         "{\n"
2480         "    uvec2 coord = uvec2(floor(gl_FragCoord.xy));\n"
2481         "    uint index = coord.x +  coord.y * 128u;\n"
2482         "    uint index_x = index / divisor1;\n"
2483         "    uint index_y = (index % divisor1) / divisor2;\n"
2484         "    my_FragColor = instance[0].s[index_x].color[index_y] + "
2485         "instance[1].s[index_x].color[index_y];\n"
2486         "}\n";
2487 
2488     GLint blockSize0, blockSize1;
2489     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS.c_str());
2490     GLint uniformBufferIndex0 = glGetUniformBlockIndex(program, "buffer[0]");
2491     GLint uniformBufferIndex1 = glGetUniformBlockIndex(program, "buffer[1]");
2492     glGetActiveUniformBlockiv(program, uniformBufferIndex0, GL_UNIFORM_BLOCK_DATA_SIZE,
2493                               &blockSize0);
2494     glGetActiveUniformBlockiv(program, uniformBufferIndex1, GL_UNIFORM_BLOCK_DATA_SIZE,
2495                               &blockSize1);
2496 
2497     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
2498     glBufferData(GL_UNIFORM_BUFFER, blockSize0, nullptr, GL_STATIC_DRAW);
2499 
2500     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
2501     glUniformBlockBinding(program, uniformBufferIndex0, 0);
2502 
2503     const GLuint arraySize  = getArraySize();
2504     const GLuint floatCount = arraySize * kVectorPerMat * kFloatPerVector;
2505     std::vector<GLfloat> floatData0(floatCount, 0.0f);
2506     std::vector<GLfloat> floatData1(floatCount, 0.0f);
2507 
2508     setArrayValues(floatData0, 0, arraySize, 16, 0, 4, 4, 0.0f, 0.0f, 1.0f, 1.0f);
2509     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData0.data());
2510 
2511     GLBuffer uniformBuffer1;
2512     glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer1);
2513     glBufferData(GL_UNIFORM_BUFFER, blockSize1, nullptr, GL_STATIC_DRAW);
2514 
2515     glBindBufferBase(GL_UNIFORM_BUFFER, 1, uniformBuffer1);
2516     glUniformBlockBinding(program, uniformBufferIndex0, 1);
2517 
2518     setArrayValues(floatData1, 0, arraySize, 16, 0, 4, 4, 0.0f, 1.0f, 0.0f, 0.0f);
2519     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData1.data());
2520     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2521     checkResults(GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan);
2522 
2523     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
2524     setArrayValues(floatData0, 0, arraySize, 16, 0, 4, 4, 1.0f, 0.0f, 0.0f, 1.0f);
2525     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData0.data());
2526     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2527     checkResults(GLColor::yellow, GLColor::yellow, GLColor::yellow, GLColor::yellow);
2528 
2529     glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer1);
2530     setArrayValues(floatData1, arraySize / 4, arraySize / 2, 16, 0, 4, 4, 0.0f, 0.0f, 1.0f, 0.0f);
2531     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData1.data());
2532     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2533     checkResults(GLColor::yellow, GLColor::magenta, GLColor::yellow, GLColor::yellow);
2534 }
2535 
2536 // Test uniform block whose member is structure type, which contains a mat4 member and a float
2537 // member.
TEST_P(UniformBlockWithOneLargeArrayMemberTest,MemberTypeIsMixStructMat4AndFloat)2538 TEST_P(UniformBlockWithOneLargeArrayMemberTest, MemberTypeIsMixStructMat4AndFloat)
2539 {
2540     std::ostringstream stream;
2541     generateArraySizeAndDivisorsDeclaration(stream, false, true, false);
2542     const std::string &kFS =
2543         "#version 300 es\n"
2544         "precision highp float;\n" +
2545         stream.str() +
2546         "out vec4 my_FragColor;\n"
2547         "struct S { mat4 color; float factor; };\n"
2548         "layout(std140) uniform buffer { S s[arraySize]; };\n"
2549         "void main()\n"
2550         "{\n"
2551         "    uvec2 coord = uvec2(floor(gl_FragCoord.xy));\n"
2552         "    uint index = coord.x +  coord.y * 128u;\n"
2553         "    uint index_x = index / divisor1;\n"
2554         "    uint index_y = (index % divisor1) / divisor2;\n"
2555         "    my_FragColor = s[index_x].factor * s[index_x].color[index_y];\n"
2556         "}\n";
2557 
2558     GLint blockSize;
2559     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS.c_str());
2560     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "buffer");
2561     glGetActiveUniformBlockiv(program, uniformBufferIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
2562 
2563     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
2564     glBufferData(GL_UNIFORM_BUFFER, blockSize, nullptr, GL_STATIC_DRAW);
2565 
2566     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
2567     glUniformBlockBinding(program, uniformBufferIndex, 0);
2568 
2569     // The member s is an array of S structures, each element of s should be rounded up
2570     // to the base alignment of a vec4 according to std140 storage layout rules.
2571     const GLuint arraySize  = getArraySize();
2572     const GLuint floatCount = arraySize * (kVectorPerMat * kFloatPerVector + kFloatPerVector);
2573     std::vector<GLfloat> floatData(floatCount, 0.0f);
2574     const size_t strideofFloatCount = kVectorPerMat * kFloatPerVector + kFloatPerVector;
2575 
2576     setArrayValues(floatData, 0, arraySize, strideofFloatCount, 0, 4, 4, 0.0f, 0.0f, 0.5f, 0.5f, 16,
2577                    1, 1, 2.0f, 0.0f, 0.0f, 0.0f);
2578     glBufferSubData(GL_UNIFORM_BUFFER, 0,
2579                     std::min(static_cast<size_t>(blockSize), floatCount * sizeof(GLfloat)),
2580                     floatData.data());
2581     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2582     checkResults(GLColor::blue, GLColor::blue, GLColor::blue, GLColor::blue);
2583 
2584     setArrayValues(floatData, 0, arraySize, strideofFloatCount, 0, 4, 4, 0.0f, 0.5f, 0.0f, 0.5f, 16,
2585                    1, 1, 2.0f, 0.0f, 0.0f, 0.0f);
2586     glBufferSubData(GL_UNIFORM_BUFFER, 0,
2587                     std::min(static_cast<size_t>(blockSize), floatCount * sizeof(GLfloat)),
2588                     floatData.data());
2589     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2590     checkResults(GLColor::green, GLColor::green, GLColor::green, GLColor::green);
2591 
2592     setArrayValues(floatData, arraySize / 4, arraySize / 2, strideofFloatCount, 0, 4, 4, 0.5f, 0.0f,
2593                    0.0f, 0.5f, 16, 1, 1, 2.0f, 0.0f, 0.0f, 0.0f);
2594     glBufferSubData(GL_UNIFORM_BUFFER, 0,
2595                     std::min(static_cast<size_t>(blockSize), floatCount * sizeof(GLfloat)),
2596                     floatData.data());
2597     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2598     checkResults(GLColor::green, GLColor::red, GLColor::green, GLColor::green);
2599 }
2600 
2601 // Test uniform block whose member is structure type, which contains a vec2 member and a vec3
2602 // member.
TEST_P(UniformBlockWithOneLargeArrayMemberTest,MemberTypeIsMixStructVec2AndVec3)2603 TEST_P(UniformBlockWithOneLargeArrayMemberTest, MemberTypeIsMixStructVec2AndVec3)
2604 {
2605     std::ostringstream stream;
2606     generateArraySizeAndDivisorsDeclaration(stream, false, false, false);
2607     const std::string &kFS =
2608         "#version 300 es\n"
2609         "precision highp float;\n" +
2610         stream.str() +
2611         "out vec4 my_FragColor;\n"
2612         "struct S { vec2 color1; vec3 color2; };\n"
2613         "layout(std140) uniform buffer { S s[arraySize]; };\n"
2614         "void main()\n"
2615         "{\n"
2616         "    uvec2 coord = uvec2(floor(gl_FragCoord.xy));\n"
2617         "    uint index = (coord.x +  coord.y * 128u) / divisor;\n"
2618         "    my_FragColor = vec4(s[index].color1, s[index].color2.xy);\n"
2619         "}\n";
2620 
2621     GLint blockSize;
2622     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS.c_str());
2623     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "buffer");
2624     glGetActiveUniformBlockiv(program, uniformBufferIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
2625 
2626     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
2627     glBufferData(GL_UNIFORM_BUFFER, blockSize, nullptr, GL_STATIC_DRAW);
2628 
2629     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
2630     glUniformBlockBinding(program, uniformBufferIndex, 0);
2631 
2632     // The base alignment of "color2" is vec4.
2633     const GLuint arraySize  = getArraySize();
2634     const GLuint floatCount = arraySize * 2 * kFloatPerVector;
2635     std::vector<GLfloat> floatData(floatCount, 0.0f);
2636     const size_t strideofFloatCount = 2 * kFloatPerVector;
2637 
2638     setArrayValues(floatData, 0, arraySize, strideofFloatCount, 0, 1, 2, 1.0f, 1.0f, 0.0f, 0.0f, 4,
2639                    1, 3, 1.0f, 1.0f, 0.0f, 0.0f);
2640     glBufferSubData(GL_UNIFORM_BUFFER, 0,
2641                     std::min(static_cast<size_t>(blockSize), floatCount * sizeof(GLfloat)),
2642                     floatData.data());
2643     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2644     checkResults(GLColor::white, GLColor::white, GLColor::white, GLColor::white);
2645 
2646     setArrayValues(floatData, 0, arraySize, strideofFloatCount, 0, 1, 2, 1.0f, 0.0f, 0.0f, 0.0f, 4,
2647                    1, 3, 0.0f, 1.0f, 0.0f, 0.0f);
2648     glBufferSubData(GL_UNIFORM_BUFFER, 0,
2649                     std::min(static_cast<size_t>(blockSize), floatCount * sizeof(GLfloat)),
2650                     floatData.data());
2651     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2652     checkResults(GLColor::red, GLColor::red, GLColor::red, GLColor::red);
2653 
2654     setArrayValues(floatData, arraySize / 4, arraySize / 2, strideofFloatCount, 0, 1, 2, 0.0f, 0.0f,
2655                    0.0f, 0.0f, 4, 1, 3, 1.0f, 1.0f, 0.0f, 0.0f);
2656     glBufferSubData(GL_UNIFORM_BUFFER, 0,
2657                     std::min(static_cast<size_t>(blockSize), floatCount * sizeof(GLfloat)),
2658                     floatData.data());
2659     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2660     checkResults(GLColor::red, GLColor::blue, GLColor::red, GLColor::red);
2661 }
2662 
2663 // Test uniform block whose member is structure type, which contains a float member and a vec3
2664 // member.
TEST_P(UniformBlockWithOneLargeArrayMemberTest,MemberTypeIsMixStructFloatAndVec3)2665 TEST_P(UniformBlockWithOneLargeArrayMemberTest, MemberTypeIsMixStructFloatAndVec3)
2666 {
2667     std::ostringstream stream;
2668     generateArraySizeAndDivisorsDeclaration(stream, false, false, false);
2669     const std::string &kFS =
2670         "#version 300 es\n"
2671         "precision highp float;\n" +
2672         stream.str() +
2673         "out vec4 my_FragColor;\n"
2674         "struct S { float color1; vec3 color2; };\n"
2675         "layout(std140) uniform buffer { S s[arraySize]; };\n"
2676         "void main()\n"
2677         "{\n"
2678         "    uvec2 coord = uvec2(floor(gl_FragCoord.xy));\n"
2679         "    uint index = (coord.x +  coord.y * 128u) / divisor;\n"
2680         "    my_FragColor = vec4(s[index].color1, s[index].color2);\n"
2681         "}\n";
2682 
2683     GLint blockSize;
2684     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS.c_str());
2685     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "buffer");
2686     glGetActiveUniformBlockiv(program, uniformBufferIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
2687 
2688     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
2689     glBufferData(GL_UNIFORM_BUFFER, blockSize, nullptr, GL_STATIC_DRAW);
2690 
2691     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
2692     glUniformBlockBinding(program, uniformBufferIndex, 0);
2693 
2694     // The base alignment of "color2" is vec4.
2695     const GLuint arraySize  = getArraySize();
2696     const GLuint floatCount = arraySize * 2 * kFloatPerVector;
2697     std::vector<GLfloat> floatData(floatCount, 0.0f);
2698     const size_t strideofFloatCount = 2 * kFloatPerVector;
2699 
2700     setArrayValues(floatData, 0, arraySize, strideofFloatCount, 0, 1, 1, 1.0f, 0.0f, 0.0f, 0.0f, 4,
2701                    1, 3, 1.0f, 1.0f, 1.0f, 0.0f);
2702     glBufferSubData(GL_UNIFORM_BUFFER, 0,
2703                     std::min(static_cast<size_t>(blockSize), floatCount * sizeof(GLfloat)),
2704                     floatData.data());
2705     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2706     checkResults(GLColor::white, GLColor::white, GLColor::white, GLColor::white);
2707 
2708     setArrayValues(floatData, 0, arraySize, strideofFloatCount, 0, 1, 1, 1.0f, 0.0f, 0.0f, 0.0f, 4,
2709                    1, 3, 0.0f, 0.0f, 1.0f, 0.0f);
2710     glBufferSubData(GL_UNIFORM_BUFFER, 0,
2711                     std::min(static_cast<size_t>(blockSize), floatCount * sizeof(GLfloat)),
2712                     floatData.data());
2713     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2714     checkResults(GLColor::red, GLColor::red, GLColor::red, GLColor::red);
2715 
2716     setArrayValues(floatData, arraySize / 4, arraySize / 2, strideofFloatCount, 0, 1, 1, 0.0f, 0.0f,
2717                    0.0f, 0.0f, 4, 1, 3, 0.0f, 1.0f, 1.0f, 0.0f);
2718     glBufferSubData(GL_UNIFORM_BUFFER, 0,
2719                     std::min(static_cast<size_t>(blockSize), floatCount * sizeof(GLfloat)),
2720                     floatData.data());
2721     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2722     checkResults(GLColor::red, GLColor::blue, GLColor::red, GLColor::red);
2723 }
2724 
2725 // Test uniform block whose member is structure type, which contains a vec3 member and a float
2726 // member.
TEST_P(UniformBlockWithOneLargeArrayMemberTest,MemberTypeIsMixStructVec3AndFloat)2727 TEST_P(UniformBlockWithOneLargeArrayMemberTest, MemberTypeIsMixStructVec3AndFloat)
2728 {
2729     std::ostringstream stream;
2730     generateArraySizeAndDivisorsDeclaration(stream, false, false, false);
2731     const std::string &kFS =
2732         "#version 300 es\n"
2733         "precision highp float;\n" +
2734         stream.str() +
2735         "out vec4 my_FragColor;\n"
2736         "struct S { vec3 color1; float color2; };\n"
2737         "layout(std140) uniform buffer { S s[arraySize]; };\n"
2738         "void main()\n"
2739         "{\n"
2740         "    uvec2 coord = uvec2(floor(gl_FragCoord.xy));\n"
2741         "    uint index = (coord.x +  coord.y * 128u) / divisor;\n"
2742         "    my_FragColor = vec4(s[index].color2, s[index].color1);\n"
2743         "}\n";
2744 
2745     GLint blockSize;
2746     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS.c_str());
2747     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "buffer");
2748     glGetActiveUniformBlockiv(program, uniformBufferIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
2749 
2750     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
2751     glBufferData(GL_UNIFORM_BUFFER, blockSize, nullptr, GL_STATIC_DRAW);
2752 
2753     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
2754     glUniformBlockBinding(program, uniformBufferIndex, 0);
2755 
2756     const GLuint arraySize  = getArraySize();
2757     const GLuint floatCount = arraySize * kFloatPerVector;
2758     std::vector<GLfloat> floatData(floatCount, 0.0f);
2759     const size_t strideofFloatCount = kFloatPerVector;
2760 
2761     setArrayValues(floatData, 0, arraySize, strideofFloatCount, 0, 1, 3, 1.0f, 1.0f, 1.0f, 0.0f, 3,
2762                    1, 1, 1.0f, 0.0f, 0.0f, 0.0f);
2763     glBufferSubData(GL_UNIFORM_BUFFER, 0,
2764                     std::min(static_cast<size_t>(blockSize), floatCount * sizeof(GLfloat)),
2765                     floatData.data());
2766     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2767     checkResults(GLColor::white, GLColor::white, GLColor::white, GLColor::white);
2768 
2769     setArrayValues(floatData, 0, arraySize, strideofFloatCount, 0, 1, 3, 0.0f, 0.0f, 1.0f, 0.0f, 3,
2770                    1, 1, 1.0f, 0.0f, 0.0f, 0.0f);
2771     glBufferSubData(GL_UNIFORM_BUFFER, 0,
2772                     std::min(static_cast<size_t>(blockSize), floatCount * sizeof(GLfloat)),
2773                     floatData.data());
2774     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2775     checkResults(GLColor::red, GLColor::red, GLColor::red, GLColor::red);
2776 
2777     setArrayValues(floatData, arraySize / 4, arraySize / 2, strideofFloatCount, 0, 1, 3, 0.0f, 1.0f,
2778                    1.0f, 0.0f, 3, 1, 1, 0.0f, 0.0f, 0.0f, 0.0f);
2779     glBufferSubData(GL_UNIFORM_BUFFER, 0,
2780                     std::min(static_cast<size_t>(blockSize), floatCount * sizeof(GLfloat)),
2781                     floatData.data());
2782     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2783     checkResults(GLColor::red, GLColor::blue, GLColor::red, GLColor::red);
2784 }
2785 
2786 // Test two uniform blocks with large structure array member are in the same program, and they
2787 // share the same uniform buffer.
TEST_P(UniformBlockWithOneLargeArrayMemberTest,TwoUniformBlocksInSameProgram)2788 TEST_P(UniformBlockWithOneLargeArrayMemberTest, TwoUniformBlocksInSameProgram)
2789 {
2790     std::ostringstream stream;
2791     generateArraySizeAndDivisorsDeclaration(stream, true, true, true);
2792     const std::string &kFS =
2793         "#version 300 es\n"
2794         "precision highp float;\n" +
2795         stream.str() +
2796         "out vec4 my_FragColor;\n"
2797         "struct S { mat4 color;};\n"
2798         "layout(std140) uniform buffer1 { S s1[arraySize1]; };\n"
2799         "layout(std140) uniform buffer2 { S s2[arraySize2]; };\n"
2800         "void main()\n"
2801         "{\n"
2802         "    uvec2 coord = uvec2(floor(gl_FragCoord.xy));\n"
2803         "    uint index = coord.x +  coord.y * 128u;\n"
2804         "    uint index_x1 = index / divisor1;\n"
2805         "    uint index_y1 = (index % divisor1) / divisor2;\n"
2806         "    uint index_x2 = coord.x / divisor3;\n"
2807         "    uint index_y2 = coord.x % 4u;\n"
2808         "    my_FragColor = s1[index_x1].color[index_y1] + s2[index_x2].color[index_y2];\n"
2809         "}\n";
2810 
2811     GLint blockSize1, blockSize2;
2812     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS.c_str());
2813     GLint uniformBufferIndex1 = glGetUniformBlockIndex(program, "buffer1");
2814     GLint uniformBufferIndex2 = glGetUniformBlockIndex(program, "buffer2");
2815     glGetActiveUniformBlockiv(program, uniformBufferIndex1, GL_UNIFORM_BLOCK_DATA_SIZE,
2816                               &blockSize1);
2817     glGetActiveUniformBlockiv(program, uniformBufferIndex2, GL_UNIFORM_BLOCK_DATA_SIZE,
2818                               &blockSize2);
2819 
2820     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
2821     glBufferData(GL_UNIFORM_BUFFER, blockSize1 + blockSize2, nullptr, GL_STATIC_DRAW);
2822 
2823     glBindBufferRange(GL_UNIFORM_BUFFER, 0, mUniformBuffer, 0, blockSize2);
2824     glUniformBlockBinding(program, uniformBufferIndex2, 0);
2825     glBindBufferRange(GL_UNIFORM_BUFFER, 1, mUniformBuffer, blockSize2, blockSize1);
2826     glUniformBlockBinding(program, uniformBufferIndex1, 1);
2827 
2828     const GLuint arraySize1  = getArraySize();
2829     const GLuint arraySize2  = getArraySize2();
2830     const GLuint floatCount1 = arraySize1 * kVectorPerMat * kFloatPerVector;
2831     const GLuint floatCount2 = arraySize2 * kVectorPerMat * kFloatPerVector;
2832     const GLuint floatCount  = floatCount1 + floatCount2;
2833     std::vector<GLfloat> floatData(floatCount, 0.0f);
2834 
2835     setArrayValues(floatData, arraySize2, arraySize1 + arraySize2, 16, 0, 4, 4, 0.0f, 0.0f, 1.0f,
2836                    1.0f);
2837     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount2 * sizeof(GLfloat), &floatData[0]);
2838     glBufferSubData(GL_UNIFORM_BUFFER, blockSize2, floatCount1 * sizeof(GLfloat),
2839                     &floatData[floatCount2]);
2840     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2841     checkResults(GLColor::blue, GLColor::blue, GLColor::blue, GLColor::blue);
2842 
2843     setArrayValues(floatData, 0, arraySize2, 16, 0, 4, 4, 0.0f, 1.0f, 0.0f, 0.0f);
2844     setArrayValues(floatData, arraySize1 / 4, arraySize2 + arraySize1 / 2, 16, 0, 4, 4, 1.0f, 0.0f,
2845                    0.0f, 1.0f);
2846     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount2 * sizeof(GLfloat), &floatData[0]);
2847     glBufferSubData(GL_UNIFORM_BUFFER, blockSize2 + floatCount1 * sizeof(GLfloat) / 4,
2848                     floatCount1 * sizeof(GLfloat) / 4, &floatData[floatCount2 + floatCount1 / 4]);
2849     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2850     checkResults(GLColor::cyan, GLColor::yellow, GLColor::cyan, GLColor::cyan);
2851 }
2852 
2853 // Test a uniform block with large struct array member and a uniform block with small
2854 // struct array member in different programs, but they share the same uniform buffer.
TEST_P(UniformBlockWithOneLargeArrayMemberTest,TwoUniformBlocksInDiffProgram)2855 TEST_P(UniformBlockWithOneLargeArrayMemberTest, TwoUniformBlocksInDiffProgram)
2856 {
2857     std::ostringstream stream1;
2858     std::ostringstream stream2;
2859     generateArraySizeAndDivisorsDeclaration(stream1, false, true, false);
2860     generateArraySizeAndDivisorsDeclaration(stream2, false, false, false);
2861 
2862     const std::string &kFS1 =
2863         "#version 300 es\n"
2864         "precision highp float;\n" +
2865         stream1.str() +
2866         "out vec4 my_FragColor;\n"
2867         "struct S { mat4 color;};\n"
2868         "layout(std140) uniform buffer { S s[arraySize]; };\n"
2869         "void main()\n"
2870         "{\n"
2871         "    uvec2 coord = uvec2(floor(gl_FragCoord.xy));\n"
2872         "    uint index = coord.x +  coord.y * 128u;\n"
2873         "    uint index_x = index / divisor1;\n"
2874         "    uint index_y = (index % divisor1) / divisor2;\n"
2875         "    my_FragColor = s[index_x].color[index_y];\n"
2876         "}\n";
2877 
2878     const std::string &kFS2 =
2879         "#version 300 es\n"
2880         "precision highp float;\n" +
2881         stream2.str() +
2882         "out vec4 my_FragColor;\n"
2883         "struct S { mat4 color;};\n"
2884         "layout(std140) uniform buffer { S s[arraySize]; };\n"
2885         "void main()\n"
2886         "{\n"
2887         "    uvec2 coord = uvec2(floor(gl_FragCoord.xy));\n"
2888         "    uint index_x = coord.x / divisor;\n"
2889         "    uint index_y = coord.x % 4u;\n"
2890         "    my_FragColor = s[index_x].color[index_y];\n"
2891         "}\n";
2892 
2893     GLint blockSize1, blockSize2;
2894     ANGLE_GL_PROGRAM(program1, essl3_shaders::vs::Simple(), kFS1.c_str());
2895     ANGLE_GL_PROGRAM(program2, essl3_shaders::vs::Simple(), kFS2.c_str());
2896     GLint uniformBufferIndex1 = glGetUniformBlockIndex(program1, "buffer");
2897     GLint uniformBufferIndex2 = glGetUniformBlockIndex(program2, "buffer");
2898     glGetActiveUniformBlockiv(program1, uniformBufferIndex1, GL_UNIFORM_BLOCK_DATA_SIZE,
2899                               &blockSize1);
2900     glGetActiveUniformBlockiv(program2, uniformBufferIndex2, GL_UNIFORM_BLOCK_DATA_SIZE,
2901                               &blockSize2);
2902 
2903     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
2904     glBufferData(GL_UNIFORM_BUFFER, std::max(blockSize1, blockSize2), nullptr, GL_STATIC_DRAW);
2905 
2906     glBindBufferRange(GL_UNIFORM_BUFFER, 0, mUniformBuffer, 0, blockSize2);
2907     glUniformBlockBinding(program2, uniformBufferIndex2, 0);
2908     glBindBufferRange(GL_UNIFORM_BUFFER, 1, mUniformBuffer, 0, blockSize1);
2909     glUniformBlockBinding(program1, uniformBufferIndex1, 1);
2910 
2911     const GLuint arraySize1  = getArraySize();
2912     const GLuint arraySize2  = getArraySize2();
2913     const GLuint floatCount1 = arraySize1 * kVectorPerMat * kFloatPerVector;
2914     const GLuint floatCount2 = arraySize2 * kVectorPerMat * kFloatPerVector;
2915     const GLuint floatCount  = floatCount1;
2916     std::vector<GLfloat> floatData(floatCount, 0.0f);
2917 
2918     setArrayValues(floatData, 0, arraySize1, 16, 0, 4, 4, 0.0f, 0.0f, 1.0f, 1.0f);
2919     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), &floatData[0]);
2920     drawQuad(program1, essl3_shaders::PositionAttrib(), 0.5f);
2921     checkResults(GLColor::blue, GLColor::blue, GLColor::blue, GLColor::blue);
2922 
2923     setArrayValues(floatData, 0, arraySize2, 16, 0, 4, 4, 0.0f, 1.0f, 0.0f, 1.0f);
2924     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount2 * sizeof(GLfloat), &floatData[0]);
2925     drawQuad(program2, essl3_shaders::PositionAttrib(), 0.5f);
2926     checkResults(GLColor::green, GLColor::green, GLColor::green, GLColor::green);
2927 
2928     setArrayValues(floatData, arraySize2, arraySize2 + arraySize1 / 2, 16, 0, 4, 4, 0.0f, 1.0f,
2929                    0.0f, 1.0f);
2930     glBufferSubData(GL_UNIFORM_BUFFER, floatCount2 * sizeof(GLfloat),
2931                     (floatCount1 / 2 - floatCount2) * sizeof(GLfloat), &floatData[0]);
2932     drawQuad(program1, essl3_shaders::PositionAttrib(), 0.5f);
2933     checkResults(GLColor::green, GLColor::green, GLColor::blue, GLColor::blue);
2934 }
2935 
2936 // Test two uniform blocks share the same uniform buffer. On D3D backend, a uniform
2937 // block with a large array member will be translated to StructuredBuffer, and the
2938 // other uniform block will be translated to cbuffer, this case verifies that update
2939 // buffer data correctly.
TEST_P(UniformBlockWithOneLargeArrayMemberTest,SharedSameBufferWithOtherOne)2940 TEST_P(UniformBlockWithOneLargeArrayMemberTest, SharedSameBufferWithOtherOne)
2941 {
2942     ANGLE_SKIP_TEST_IF(IsIntel() && IsMac() && IsOpenGL());
2943 
2944     std::ostringstream stream;
2945     generateArraySizeAndDivisorsDeclaration(stream, false, true, false);
2946     const std::string &kFS =
2947         "#version 300 es\n"
2948         "precision highp float;\n" +
2949         stream.str() +
2950         "out vec4 my_FragColor;\n"
2951         "struct S { mat4 color;};\n"
2952         "layout(std140) uniform buffer { S s[arraySize]; };\n"
2953         "layout(std140) uniform buffer1 { vec4 factor; };\n"
2954         "void main()\n"
2955         "{\n"
2956         "    uvec2 coord = uvec2(floor(gl_FragCoord.xy));\n"
2957         "    uint index = coord.x +  coord.y * 128u;\n"
2958         "    uint index_x = index / divisor1;\n"
2959         "    uint index_y = (index % divisor1) / divisor2;\n"
2960         "    my_FragColor = s[index_x].color[index_y] + factor;\n"
2961         "}\n";
2962 
2963     GLint blockSize;
2964     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS.c_str());
2965     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "buffer");
2966     glGetActiveUniformBlockiv(program, uniformBufferIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
2967     GLint uniformBufferIndex1 = glGetUniformBlockIndex(program, "buffer1");
2968     GLint alignment;
2969     glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &alignment);
2970     while (alignment >= 0 && alignment < 16)
2971     {
2972         alignment += alignment;
2973     }
2974 
2975     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
2976     glBufferData(GL_UNIFORM_BUFFER, alignment + blockSize, nullptr, GL_STATIC_DRAW);
2977 
2978     const GLuint arraySize  = getArraySize();
2979     const GLuint floatCount = arraySize * kVectorPerMat * kFloatPerVector;
2980     std::vector<GLfloat> floatData(floatCount, 0.0f);
2981     std::vector<GLfloat> floatData1(4, 0.0f);
2982 
2983     setArrayValues(floatData, 0, arraySize, 16, 0, 4, 4, 0.0f, 0.0f, 0.5f, 0.5f);
2984     setArrayValues(floatData1, 0, 1, 4, 0, 1, 4, 1.0f, 0.0f, 0.5f, 0.5f);
2985     glBindBufferRange(GL_UNIFORM_BUFFER, 0, mUniformBuffer, 0, 4 * sizeof(float));
2986     glUniformBlockBinding(program, uniformBufferIndex1, 0);
2987     glBindBufferRange(GL_UNIFORM_BUFFER, 1, mUniformBuffer, alignment, floatCount * sizeof(float));
2988     glUniformBlockBinding(program, uniformBufferIndex, 1);
2989 
2990     glBufferSubData(GL_UNIFORM_BUFFER, alignment, floatCount * sizeof(GLfloat), floatData.data());
2991     glBufferSubData(GL_UNIFORM_BUFFER, 0, 4 * sizeof(GLfloat), floatData1.data());
2992     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2993     checkResults(GLColor::magenta, GLColor::magenta, GLColor::magenta, GLColor::magenta);
2994 
2995     setArrayValues(floatData, 0, arraySize, 16, 0, 4, 4, 0.0f, 0.5f, 0.0f, 0.5f);
2996     setArrayValues(floatData1, 0, 1, 4, 0, 1, 4, 0.0f, 0.5f, 0.0f, 0.5f);
2997     glBufferSubData(GL_UNIFORM_BUFFER, alignment, floatCount * sizeof(GLfloat), floatData.data());
2998     glBufferSubData(GL_UNIFORM_BUFFER, 0, 4 * sizeof(GLfloat), floatData1.data());
2999     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3000     checkResults(GLColor::green, GLColor::green, GLColor::green, GLColor::green);
3001 }
3002 
3003 // Test indexing accesses uniform block with a large matrix array member correctly.
TEST_P(UniformBlockWithOneLargeArrayMemberTest,MemberTypeIsMatrixAndIndexAccess)3004 TEST_P(UniformBlockWithOneLargeArrayMemberTest, MemberTypeIsMatrixAndIndexAccess)
3005 {
3006     const char *kFS = R"(#version 300 es
3007 precision mediump float;
3008 
3009 uniform uint index;
3010 
3011 struct S { uvec4 idx; };
3012 
3013 layout(std140) uniform idxbuf { S idxArray[2]; };
3014 
3015 layout(std140) uniform buffer1 { mat4 s1[128]; };
3016 layout(std140) uniform buffer2 { mat4 s2[128]; } buf2[2];
3017 
3018 out vec4 fragColor;
3019 void main()
3020 {
3021   fragColor = s1[1][0] + s1[index][1] + s1[idxArray[0].idx.x][idxArray[1].idx.z]
3022   + buf2[0].s2[1][0] + buf2[1].s2[index][1] + buf2[0].s2[idxArray[0].idx.y][idxArray[1].idx.z]
3023   + vec4(buf2[1].s2[index][1][index], s1[1][0][2], s1[idxArray[0].idx.x][idxArray[1].idx.z][2],
3024   buf2[0].s2[idxArray[0].idx.y][idxArray[1].idx.z][3]);
3025 })";
3026 
3027     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3028     ASSERT_GL_NO_ERROR();
3029 }
3030 
3031 // Test uniform block whose member is matrix type.
TEST_P(UniformBlockWithOneLargeArrayMemberTest,MemberTypeIsMatrix)3032 TEST_P(UniformBlockWithOneLargeArrayMemberTest, MemberTypeIsMatrix)
3033 {
3034     std::ostringstream stream;
3035     generateArraySizeAndDivisorsDeclaration(stream, false, true, false);
3036     const std::string &kFS =
3037         "#version 300 es\n"
3038         "precision highp float;\n" +
3039         stream.str() +
3040         "out vec4 my_FragColor;\n"
3041         "layout(std140) uniform buffer { mat4 s[arraySize]; };\n"
3042         "void main()\n"
3043         "{\n"
3044         "    uvec2 coord = uvec2(floor(gl_FragCoord.xy));\n"
3045         "    uint index = coord.x +  coord.y * 128u;\n"
3046         "    uint index_x = index / divisor1;\n"
3047         "    uint index_y = (index % divisor1) / divisor2;\n"
3048         "    my_FragColor = s[index_x][index_y];\n"
3049         "}\n";
3050 
3051     GLint blockSize;
3052     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS.c_str());
3053     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "buffer");
3054     glGetActiveUniformBlockiv(program, uniformBufferIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
3055 
3056     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
3057     glBufferData(GL_UNIFORM_BUFFER, blockSize, nullptr, GL_STATIC_DRAW);
3058 
3059     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
3060     glUniformBlockBinding(program, uniformBufferIndex, 0);
3061 
3062     const GLuint arraySize  = getArraySize();
3063     const GLuint floatCount = arraySize * kVectorPerMat * kFloatPerVector;
3064     std::vector<GLfloat> floatData(floatCount, 0.0f);
3065 
3066     setArrayValues(floatData, 0, arraySize, 16, 0, 4, 4, 0.0f, 0.0f, 1.0f, 1.0f);
3067     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData.data());
3068     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3069     checkResults(GLColor::blue, GLColor::blue, GLColor::blue, GLColor::blue);
3070 
3071     setArrayValues(floatData, 0, arraySize, 16, 0, 4, 4, 0.0f, 1.0f, 0.0f, 1.0f);
3072     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData.data());
3073     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3074     checkResults(GLColor::green, GLColor::green, GLColor::green, GLColor::green);
3075 
3076     setArrayValues(floatData, arraySize / 4, arraySize / 2, 16, 0, 4, 4, 1.0f, 0.0f, 0.0f, 1.0f);
3077     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData.data());
3078     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3079     checkResults(GLColor::green, GLColor::red, GLColor::green, GLColor::green);
3080 }
3081 
3082 // Test instanced uniform block whose member is matrix type.
TEST_P(UniformBlockWithOneLargeArrayMemberTest,MemberTypeIsMatrixAndInstanced)3083 TEST_P(UniformBlockWithOneLargeArrayMemberTest, MemberTypeIsMatrixAndInstanced)
3084 {
3085     std::ostringstream stream;
3086     generateArraySizeAndDivisorsDeclaration(stream, false, true, false);
3087     const std::string &kFS =
3088         "#version 300 es\n"
3089         "precision highp float;\n" +
3090         stream.str() +
3091         "out vec4 my_FragColor;\n"
3092         "layout(std140) uniform buffer { mat4 s[arraySize]; } instance[2];\n"
3093         "void main()\n"
3094         "{\n"
3095         "    uvec2 coord = uvec2(floor(gl_FragCoord.xy));\n"
3096         "    uint index = coord.x +  coord.y * 128u;\n"
3097         "    uint index_x = index / divisor1;\n"
3098         "    uint index_y = (index % divisor1) / divisor2;\n"
3099         "    my_FragColor = instance[0].s[index_x][index_y] + "
3100         "instance[1].s[index_x][index_y];\n"
3101         "}\n";
3102 
3103     GLint blockSize0, blockSize1;
3104     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS.c_str());
3105     GLint uniformBufferIndex0 = glGetUniformBlockIndex(program, "buffer[0]");
3106     GLint uniformBufferIndex1 = glGetUniformBlockIndex(program, "buffer[1]");
3107     glGetActiveUniformBlockiv(program, uniformBufferIndex0, GL_UNIFORM_BLOCK_DATA_SIZE,
3108                               &blockSize0);
3109     glGetActiveUniformBlockiv(program, uniformBufferIndex1, GL_UNIFORM_BLOCK_DATA_SIZE,
3110                               &blockSize1);
3111 
3112     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
3113     glBufferData(GL_UNIFORM_BUFFER, blockSize0, nullptr, GL_STATIC_DRAW);
3114 
3115     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
3116     glUniformBlockBinding(program, uniformBufferIndex0, 0);
3117 
3118     const GLuint arraySize  = getArraySize();
3119     const GLuint floatCount = arraySize * kVectorPerMat * kFloatPerVector;
3120     std::vector<GLfloat> floatData0(floatCount, 0.0f);
3121     std::vector<GLfloat> floatData1(floatCount, 0.0f);
3122 
3123     setArrayValues(floatData0, 0, arraySize, 16, 0, 4, 4, 0.0f, 0.0f, 1.0f, 1.0f);
3124     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData0.data());
3125 
3126     GLBuffer uniformBuffer1;
3127     glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer1);
3128     glBufferData(GL_UNIFORM_BUFFER, blockSize1, nullptr, GL_STATIC_DRAW);
3129 
3130     glBindBufferBase(GL_UNIFORM_BUFFER, 1, uniformBuffer1);
3131     glUniformBlockBinding(program, uniformBufferIndex0, 1);
3132 
3133     setArrayValues(floatData1, 0, arraySize, 16, 0, 4, 4, 0.0f, 1.0f, 0.0f, 0.0f);
3134     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData1.data());
3135     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3136     checkResults(GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan);
3137 
3138     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
3139     setArrayValues(floatData0, 0, arraySize, 16, 0, 4, 4, 1.0f, 0.0f, 0.0f, 1.0f);
3140     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData0.data());
3141     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3142     checkResults(GLColor::yellow, GLColor::yellow, GLColor::yellow, GLColor::yellow);
3143 
3144     glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer1);
3145     setArrayValues(floatData1, arraySize / 4, arraySize / 2, 16, 0, 4, 4, 0.0f, 0.0f, 1.0f, 0.0f);
3146     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData1.data());
3147     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3148     checkResults(GLColor::yellow, GLColor::magenta, GLColor::yellow, GLColor::yellow);
3149 }
3150 
3151 // Test uniform block with row major qualifier whose member is matrix type.
TEST_P(UniformBlockWithOneLargeArrayMemberTest,MemberTypeIsMatrixAndRowMajorQualifier)3152 TEST_P(UniformBlockWithOneLargeArrayMemberTest, MemberTypeIsMatrixAndRowMajorQualifier)
3153 {
3154     // http://anglebug.com/42262481 , http://anglebug.com/40096480
3155     ANGLE_SKIP_TEST_IF((IsMac() && IsOpenGL()) || IsAndroid() || (IsAMD() && IsOpenGL()) ||
3156                        (IsLinux() && IsIntel() && IsOpenGL()));
3157 
3158     std::ostringstream stream;
3159     generateArraySizeAndDivisorsDeclaration(stream, false, true, false);
3160     const std::string &kFS =
3161         "#version 300 es\n"
3162         "precision highp float;\n" +
3163         stream.str() +
3164         "out vec4 my_FragColor;\n"
3165         "layout(std140, row_major) uniform buffer { mat4 s[arraySize]; };\n"
3166         "void main()\n"
3167         "{\n"
3168         "    uvec2 coord = uvec2(floor(gl_FragCoord.xy));\n"
3169         "    uint index = coord.x +  coord.y * 128u;\n"
3170         "    uint index_x = index / divisor1;\n"
3171         "    uint index_y = (index % divisor1) / divisor2;\n"
3172         "    my_FragColor = s[index_x][index_y];\n"
3173         "}\n";
3174 
3175     GLint blockSize;
3176     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS.c_str());
3177     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "buffer");
3178     glGetActiveUniformBlockiv(program, uniformBufferIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
3179 
3180     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
3181     glBufferData(GL_UNIFORM_BUFFER, blockSize, nullptr, GL_STATIC_DRAW);
3182 
3183     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
3184     glUniformBlockBinding(program, uniformBufferIndex, 0);
3185 
3186     const GLuint arraySize  = getArraySize();
3187     const GLuint floatCount = arraySize * kVectorPerMat * kFloatPerVector;
3188     std::vector<GLfloat> floatData(floatCount, 0.0f);
3189 
3190     setArrayValues(floatData, 0, arraySize, 16, 0, 2, 4, 0.0f, 0.0f, 0.0f, 0.0f, 8, 2, 4, 1.0f,
3191                    1.0f, 1.0f, 1.0f);
3192     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData.data());
3193     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3194     checkResults(GLColor::blue, GLColor::blue, GLColor::blue, GLColor::blue);
3195 
3196     setArrayValues(floatData, 0, arraySize, 16, 4, 1, 4, 1.0f, 1.0f, 1.0f, 1.0f, 8, 1, 4, 0.0f,
3197                    0.0f, 0.0f, 0.0f);
3198     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData.data());
3199     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3200     checkResults(GLColor::green, GLColor::green, GLColor::green, GLColor::green);
3201 
3202     setArrayValues(floatData, arraySize / 4, arraySize / 2, 16, 0, 1, 4, 1.0f, 1.0f, 1.0f, 1.0f, 4,
3203                    1, 4, 0.0f, 0.0f, 0.0f, 0.0f);
3204     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData.data());
3205     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3206     checkResults(GLColor::green, GLColor::red, GLColor::green, GLColor::green);
3207 }
3208 
3209 // Test uniform block whose member is vec4 type.
TEST_P(UniformBlockWithOneLargeArrayMemberTest,MemberTypeIsVec4)3210 TEST_P(UniformBlockWithOneLargeArrayMemberTest, MemberTypeIsVec4)
3211 {
3212     std::ostringstream stream;
3213     generateArraySizeAndDivisorsDeclaration(stream, false, false, false);
3214     const std::string &kFS =
3215         "#version 300 es\n"
3216         "precision highp float;\n" +
3217         stream.str() +
3218         "out vec4 my_FragColor;\n"
3219         "layout(std140) uniform buffer { vec4 s[arraySize]; };\n"
3220         "void main()\n"
3221         "{\n"
3222         "    uvec2 coord = uvec2(floor(gl_FragCoord.xy));\n"
3223         "    uint index = (coord.x +  coord.y * 128u) / divisor;\n"
3224         "    my_FragColor = s[index];\n"
3225         "}\n";
3226 
3227     GLint blockSize;
3228     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS.c_str());
3229     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "buffer");
3230     glGetActiveUniformBlockiv(program, uniformBufferIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
3231 
3232     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
3233     glBufferData(GL_UNIFORM_BUFFER, blockSize, nullptr, GL_STATIC_DRAW);
3234 
3235     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
3236     glUniformBlockBinding(program, uniformBufferIndex, 0);
3237 
3238     const GLuint arraySize  = getArraySize();
3239     const GLuint floatCount = arraySize * kFloatPerVector;
3240     std::vector<GLfloat> floatData(floatCount, 0.0f);
3241 
3242     setArrayValues(floatData, 0, arraySize, 4, 0, 1, 4, 1.0f, 0.0f, 1.0f, 1.0f);
3243     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData.data());
3244     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3245     checkResults(GLColor::magenta, GLColor::magenta, GLColor::magenta, GLColor::magenta);
3246 
3247     setArrayValues(floatData, 0, arraySize, 4, 0, 1, 4, 1.0f, 1.0f, 0.0f, 1.0f);
3248     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData.data());
3249     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3250     checkResults(GLColor::yellow, GLColor::yellow, GLColor::yellow, GLColor::yellow);
3251 }
3252 
3253 // Test uniform block whose member is vec3 type.
TEST_P(UniformBlockWithOneLargeArrayMemberTest,MemberTypeIsVec3)3254 TEST_P(UniformBlockWithOneLargeArrayMemberTest, MemberTypeIsVec3)
3255 {
3256     std::ostringstream stream;
3257     generateArraySizeAndDivisorsDeclaration(stream, false, false, false);
3258     const std::string &kFS =
3259         "#version 300 es\n"
3260         "precision highp float;\n" +
3261         stream.str() +
3262         "out vec4 my_FragColor;\n"
3263         "layout(std140) uniform buffer { vec3 s[arraySize]; };\n"
3264         "void main()\n"
3265         "{\n"
3266         "    uvec2 coord = uvec2(floor(gl_FragCoord.xy));\n"
3267         "    uint index = (coord.x +  coord.y * 128u) / divisor;\n"
3268         "    my_FragColor = vec4(s[index], 1.0);\n"
3269         "}\n";
3270 
3271     GLint blockSize;
3272     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS.c_str());
3273     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "buffer");
3274     glGetActiveUniformBlockiv(program, uniformBufferIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
3275 
3276     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
3277     glBufferData(GL_UNIFORM_BUFFER, blockSize, nullptr, GL_STATIC_DRAW);
3278 
3279     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
3280     glUniformBlockBinding(program, uniformBufferIndex, 0);
3281 
3282     const GLuint arraySize  = getArraySize();
3283     const GLuint floatCount = arraySize * kFloatPerVector;
3284     std::vector<GLfloat> floatData(floatCount, 0.0f);
3285 
3286     setArrayValues(floatData, 0, arraySize, 4, 0, 1, 3, 0.0f, 0.0f, 1.0f, 0.0f);
3287     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData.data());
3288     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3289     checkResults(GLColor::blue, GLColor::blue, GLColor::blue, GLColor::blue);
3290 
3291     setArrayValues(floatData, 0, arraySize, 4, 0, 1, 3, 0.0f, 1.0f, 0.0f, 0.0f);
3292     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData.data());
3293     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3294     checkResults(GLColor::green, GLColor::green, GLColor::green, GLColor::green);
3295 
3296     setArrayValues(floatData, arraySize / 4, arraySize / 2, 4, 0, 1, 3, 1.0f, 0.0f, 0.0f, 0.0f);
3297     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData.data());
3298     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3299     checkResults(GLColor::green, GLColor::red, GLColor::green, GLColor::green);
3300 }
3301 
3302 // Test uniform block whose member is vec2 type.
TEST_P(UniformBlockWithOneLargeArrayMemberTest,MemberTypeIsVec2)3303 TEST_P(UniformBlockWithOneLargeArrayMemberTest, MemberTypeIsVec2)
3304 {
3305     std::ostringstream stream;
3306     generateArraySizeAndDivisorsDeclaration(stream, false, false, false);
3307     const std::string &kFS =
3308         "#version 300 es\n"
3309         "precision highp float;\n" +
3310         stream.str() +
3311         "out vec4 my_FragColor;\n"
3312         "layout(std140) uniform buffer { vec2 s[arraySize]; };\n"
3313         "void main()\n"
3314         "{\n"
3315         "    uvec2 coord = uvec2(floor(gl_FragCoord.xy));\n"
3316         "    uint index = (coord.x +  coord.y * 128u) / divisor;\n"
3317         "    my_FragColor = vec4(s[index], s[index].x, 1.0);\n"
3318         "}\n";
3319 
3320     GLint blockSize;
3321     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS.c_str());
3322     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "buffer");
3323     glGetActiveUniformBlockiv(program, uniformBufferIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
3324 
3325     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
3326     glBufferData(GL_UNIFORM_BUFFER, blockSize, nullptr, GL_STATIC_DRAW);
3327 
3328     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
3329     glUniformBlockBinding(program, uniformBufferIndex, 0);
3330 
3331     const GLuint arraySize  = getArraySize();
3332     const GLuint floatCount = arraySize * kFloatPerVector;
3333     std::vector<GLfloat> floatData(floatCount, 0.0f);
3334 
3335     setArrayValues(floatData, 0, arraySize, 4, 0, 1, 2, 1.0f, 0.0f, 0.0f, 0.0f);
3336     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData.data());
3337     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3338     checkResults(GLColor::magenta, GLColor::magenta, GLColor::magenta, GLColor::magenta);
3339 
3340     setArrayValues(floatData, 0, arraySize, 4, 0, 1, 2, 0.0f, 1.0f, 0.0f, 0.0f);
3341     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData.data());
3342     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3343     checkResults(GLColor::green, GLColor::green, GLColor::green, GLColor::green);
3344 
3345     setArrayValues(floatData, arraySize / 4, arraySize / 2, 4, 0, 1, 2, 1.0f, 0.0f, 0.0f, 0.0f);
3346     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData.data());
3347     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3348     checkResults(GLColor::green, GLColor::magenta, GLColor::green, GLColor::green);
3349 }
3350 
3351 // Test uniform block whose member is float type.
TEST_P(UniformBlockWithOneLargeArrayMemberTest,MemberTypeIsFloat)3352 TEST_P(UniformBlockWithOneLargeArrayMemberTest, MemberTypeIsFloat)
3353 {
3354     std::ostringstream stream;
3355     generateArraySizeAndDivisorsDeclaration(stream, false, false, false);
3356     const std::string &kFS =
3357         "#version 300 es\n"
3358         "precision highp float;\n" +
3359         stream.str() +
3360         "out vec4 my_FragColor;\n"
3361         "layout(std140) uniform buffer { float s[arraySize]; };\n"
3362         "void main()\n"
3363         "{\n"
3364         "    uvec2 coord = uvec2(floor(gl_FragCoord.xy));\n"
3365         "    uint index = (coord.x +  coord.y * 128u) / divisor;\n"
3366         "    my_FragColor = vec4(s[index], 0.0, 0.0, 1.0);\n"
3367         "}\n";
3368 
3369     GLint blockSize;
3370     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS.c_str());
3371     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "buffer");
3372     glGetActiveUniformBlockiv(program, uniformBufferIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
3373 
3374     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
3375     glBufferData(GL_UNIFORM_BUFFER, blockSize, nullptr, GL_STATIC_DRAW);
3376 
3377     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
3378     glUniformBlockBinding(program, uniformBufferIndex, 0);
3379 
3380     // The base alignment and array stride are rounded up to the base alignment of a vec4.
3381     const GLuint arraySize  = getArraySize();
3382     const GLuint floatCount = arraySize * kFloatPerVector;
3383     std::vector<GLfloat> floatData(floatCount, 0.0f);
3384 
3385     setArrayValues(floatData, 0, arraySize, 4, 0, 1, 1, 1.0f, 0.0f, 0.0f, 0.0f);
3386     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData.data());
3387     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3388     checkResults(GLColor::red, GLColor::red, GLColor::red, GLColor::red);
3389 
3390     setArrayValues(floatData, arraySize / 4, arraySize / 2, 4, 0, 1, 1, 0.0f, 0.0f, 0.0f, 0.0f);
3391     glBufferSubData(GL_UNIFORM_BUFFER, 0, floatCount * sizeof(GLfloat), floatData.data());
3392     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3393     checkResults(GLColor::red, GLColor::black, GLColor::red, GLColor::red);
3394 }
3395 
3396 // Test uniform block whose member is structure type, which contains a float member and a mat4
3397 // member.
TEST_P(UniformBlockWithOneLargeArrayMemberTest,MemberTypeIsMixStructFloatAndMat4)3398 TEST_P(UniformBlockWithOneLargeArrayMemberTest, MemberTypeIsMixStructFloatAndMat4)
3399 {
3400     std::ostringstream stream;
3401     generateArraySizeAndDivisorsDeclaration(stream, false, true, false);
3402     const std::string &kFS =
3403         "#version 300 es\n"
3404         "precision highp float;\n" +
3405         stream.str() +
3406         "out vec4 my_FragColor;\n"
3407         "struct S { float factor; mat4 color; };\n"
3408         "layout(std140) uniform buffer { S s[arraySize]; };\n"
3409         "void main()\n"
3410         "{\n"
3411         "    uvec2 coord = uvec2(floor(gl_FragCoord.xy));\n"
3412         "    uint index = coord.x +  coord.y * 128u;\n"
3413         "    uint index_x = index / divisor1;\n"
3414         "    uint index_y = (index % divisor1) / divisor2;\n"
3415         "    my_FragColor = s[index_x].factor * s[index_x].color[index_y];\n"
3416         "}\n";
3417 
3418     GLint blockSize;
3419     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS.c_str());
3420     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "buffer");
3421     glGetActiveUniformBlockiv(program, uniformBufferIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
3422 
3423     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
3424     glBufferData(GL_UNIFORM_BUFFER, blockSize, nullptr, GL_STATIC_DRAW);
3425 
3426     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
3427     glUniformBlockBinding(program, uniformBufferIndex, 0);
3428 
3429     // The member s is an array of S structures, each element of s should be rounded up
3430     // to the base alignment of a vec4 according to std140 storage layout rules.
3431     const GLuint arraySize  = getArraySize();
3432     const GLuint floatCount = arraySize * (kVectorPerMat * kFloatPerVector + kFloatPerVector);
3433     std::vector<GLfloat> floatData(floatCount, 0.0f);
3434     const size_t strideofFloatCount = kVectorPerMat * kFloatPerVector + kFloatPerVector;
3435 
3436     setArrayValues(floatData, 0, arraySize, strideofFloatCount, 0, 1, 1, 2.0f, 0.0f, 0.0f, 0.0f, 4,
3437                    4, 4, 0.0f, 0.0f, 0.5f, 0.5f);
3438     glBufferSubData(GL_UNIFORM_BUFFER, 0,
3439                     std::min(static_cast<size_t>(blockSize), floatCount * sizeof(GLfloat)),
3440                     floatData.data());
3441     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3442     checkResults(GLColor::blue, GLColor::blue, GLColor::blue, GLColor::blue);
3443 
3444     setArrayValues(floatData, 0, arraySize, strideofFloatCount, 0, 1, 1, 2.0f, 0.0f, 0.0f, 0.0f, 4,
3445                    4, 4, 0.0f, 0.5f, 0.0f, 0.5f);
3446     glBufferSubData(GL_UNIFORM_BUFFER, 0,
3447                     std::min(static_cast<size_t>(blockSize), floatCount * sizeof(GLfloat)),
3448                     floatData.data());
3449     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3450     checkResults(GLColor::green, GLColor::green, GLColor::green, GLColor::green);
3451 
3452     setArrayValues(floatData, arraySize / 4, arraySize / 2, strideofFloatCount, 0, 1, 1, 2.0f, 0.0f,
3453                    0.0f, 0.0f, 4, 4, 4, 0.5f, 0.0f, 0.0f, 0.5f);
3454     glBufferSubData(GL_UNIFORM_BUFFER, 0,
3455                     std::min(static_cast<size_t>(blockSize), floatCount * sizeof(GLfloat)),
3456                     floatData.data());
3457     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3458     checkResults(GLColor::green, GLColor::red, GLColor::green, GLColor::green);
3459 }
3460 
3461 // Test uniform block whose member is structure type, which contains a float member and a vec4
3462 // member.
TEST_P(UniformBlockWithOneLargeArrayMemberTest,MemberTypeIsMixStructFloatAndVec4)3463 TEST_P(UniformBlockWithOneLargeArrayMemberTest, MemberTypeIsMixStructFloatAndVec4)
3464 {
3465     std::ostringstream stream;
3466     generateArraySizeAndDivisorsDeclaration(stream, false, false, false);
3467     const std::string &kFS =
3468         "#version 300 es\n"
3469         "precision highp float;\n" +
3470         stream.str() +
3471         "out vec4 my_FragColor;\n"
3472         "struct S { float color1; vec4 color2; };\n"
3473         "layout(std140) uniform buffer { S s[arraySize]; };\n"
3474         "void main()\n"
3475         "{\n"
3476         "    uvec2 coord = uvec2(floor(gl_FragCoord.xy));\n"
3477         "    uint index = (coord.x +  coord.y * 128u) / divisor;\n"
3478         "    my_FragColor = vec4(s[index].color1, s[index].color2.xyz);\n"
3479         "}\n";
3480 
3481     GLint blockSize;
3482     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS.c_str());
3483     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "buffer");
3484     glGetActiveUniformBlockiv(program, uniformBufferIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
3485 
3486     glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
3487     glBufferData(GL_UNIFORM_BUFFER, blockSize, nullptr, GL_STATIC_DRAW);
3488 
3489     glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
3490     glUniformBlockBinding(program, uniformBufferIndex, 0);
3491 
3492     const GLuint arraySize  = getArraySize();
3493     const GLuint floatCount = arraySize * 2 * kFloatPerVector;
3494     std::vector<GLfloat> floatData(floatCount, 0.0f);
3495     const size_t strideofFloatCount = 2 * kFloatPerVector;
3496 
3497     setArrayValues(floatData, 0, arraySize, strideofFloatCount, 0, 1, 1, 1.0f, 0.0f, 0.0f, 0.0f, 4,
3498                    1, 4, 1.0f, 1.0f, 1.0f, 0.0f);
3499     glBufferSubData(GL_UNIFORM_BUFFER, 0,
3500                     std::min(static_cast<size_t>(blockSize), floatCount * sizeof(GLfloat)),
3501                     floatData.data());
3502     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3503     checkResults(GLColor::white, GLColor::white, GLColor::white, GLColor::white);
3504 
3505     setArrayValues(floatData, 0, arraySize, strideofFloatCount, 0, 1, 1, 1.0f, 0.0f, 0.0f, 0.0f, 4,
3506                    1, 4, 0.0f, 0.0f, 1.0f, 0.0f);
3507     glBufferSubData(GL_UNIFORM_BUFFER, 0,
3508                     std::min(static_cast<size_t>(blockSize), floatCount * sizeof(GLfloat)),
3509                     floatData.data());
3510     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3511     checkResults(GLColor::red, GLColor::red, GLColor::red, GLColor::red);
3512 
3513     setArrayValues(floatData, arraySize / 4, arraySize / 2, strideofFloatCount, 0, 1, 1, 0.0f, 0.0f,
3514                    0.0f, 0.0f, 4, 1, 4, 0.0f, 1.0f, 1.0f, 0.0f);
3515     glBufferSubData(GL_UNIFORM_BUFFER, 0,
3516                     std::min(static_cast<size_t>(blockSize), floatCount * sizeof(GLfloat)),
3517                     floatData.data());
3518     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3519     checkResults(GLColor::red, GLColor::blue, GLColor::red, GLColor::red);
3520 }
3521 
3522 // Test to transfer a uniform block large array member as an actual parameter to a function.
TEST_P(UniformBlockWithOneLargeArrayMemberTest,MemberAsActualParameter)3523 TEST_P(UniformBlockWithOneLargeArrayMemberTest, MemberAsActualParameter)
3524 {
3525     ANGLE_SKIP_TEST_IF(IsAdreno());
3526 
3527     constexpr char kVS[] = R"(#version 300 es
3528 layout(location=0) in vec3 a_position;
3529 
3530 layout(std140) uniform UBO1{
3531     mat4x4 buf1[90];
3532 } instance;
3533 
3534 layout(std140) uniform UBO2{
3535     mat4x4 buf2[90];
3536 };
3537 
3538 vec4 test(mat4x4[90] para1, mat4x4[90] para2, vec3 pos){
3539     return para1[0] * para2[0] * vec4(pos, 1.0);
3540 }
3541 
3542 void main(void){
3543     gl_Position = test(instance.buf1, buf2, a_position);
3544 })";
3545 
3546     constexpr char kFS[] = R"(#version 300 es
3547 precision mediump float;
3548 
3549 uniform vec3 u_color;
3550 out vec4 oFragColor;
3551 
3552 void main(void){
3553     oFragColor = vec4( u_color, 1.0);
3554 })";
3555 
3556     ANGLE_GL_PROGRAM(program, kVS, kFS);
3557     EXPECT_GL_NO_ERROR();
3558 }
3559 
3560 // Test array operators to operate on uniform block large array member.
TEST_P(UniformBlockWithOneLargeArrayMemberTest,MemberArrayOperations)3561 TEST_P(UniformBlockWithOneLargeArrayMemberTest, MemberArrayOperations)
3562 {
3563     ANGLE_SKIP_TEST_IF(IsOpenGL() || IsOpenGLES());
3564 
3565     constexpr char kVS[] = R"(#version 300 es
3566 layout(location=0) in vec3 a_position;
3567 
3568 layout(std140) uniform UBO1{
3569     mat4x4 buf1[90];
3570 };
3571 
3572 layout(std140) uniform UBO2{
3573     mat4x4 buf2[90];
3574 };
3575 
3576 layout(std140) uniform UBO3{
3577     mat4x4 buf[90];
3578 } instance;
3579 
3580 vec4 test1( mat4x4[90] para, vec3 pos ){
3581     return para[ 0 ] * vec4( pos, 1.0 );
3582 }
3583 
3584 mat4x4[90] test2()
3585 {
3586     return instance.buf;
3587 }
3588 
3589 void main(void){
3590     if (buf1 == buf2)
3591     {
3592         mat4x4 temp1[90] = buf1;
3593         gl_Position = test1(temp1, a_position);
3594     }
3595     else
3596     {
3597         mat4x4 temp2[90] = test2();
3598         gl_Position = test1(temp2, a_position);
3599     }
3600 })";
3601 
3602     constexpr char kFS[] = R"(#version 300 es
3603 precision mediump float;
3604 
3605 uniform vec3 u_color;
3606 out vec4 oFragColor;
3607 
3608 void main(void){
3609     oFragColor = vec4( u_color, 1.0);
3610 })";
3611 
3612     ANGLE_GL_PROGRAM(program, kVS, kFS);
3613     EXPECT_GL_NO_ERROR();
3614 }
3615 
3616 // Test to throw a warning if a uniform block with a large array member
3617 // fails to hit the optimization on D3D backend.
TEST_P(UniformBlockWithOneLargeArrayMemberTest,ThrowPerfWarningInD3D)3618 TEST_P(UniformBlockWithOneLargeArrayMemberTest, ThrowPerfWarningInD3D)
3619 {
3620     constexpr char kFS[] = R"(#version 300 es
3621 precision highp float;
3622 
3623 struct S1 {
3624     vec2 a[2];
3625 };
3626 
3627 struct S2 {
3628     mat2x4 b;
3629 };
3630 
3631 layout(std140, row_major) uniform UBO1{
3632     mat3x2 buf1[128];
3633 };
3634 
3635 layout(std140, row_major) uniform UBO2{
3636     mat4x3 buf2[128];
3637 } instance1;
3638 
3639 layout(std140, row_major) uniform UBO3{
3640     S1 buf3[128];
3641 };
3642 
3643 layout(std140, row_major) uniform UBO4{
3644     S2 buf4[128];
3645 } instance2[2];
3646 
3647 out vec4 my_FragColor;
3648 
3649 void main(void){
3650     uvec2 coord = uvec2(floor(gl_FragCoord.xy));
3651     uint x = coord.x % 64u;
3652     uint y = coord.y;
3653     my_FragColor = vec4(buf1[y]*instance1.buf2[y]*instance2[0].buf4[y].b*buf3[y].a[x], 0.0f, 1.0);
3654 
3655 })";
3656 
3657     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
3658     EXPECT_GL_NO_ERROR();
3659 }
3660 
3661 // Tests rendering with a bound, unreferenced UBO that has no data. Covers a paticular back-end bug.
TEST_P(UniformBufferTest,EmptyUnusedUniformBuffer)3662 TEST_P(UniformBufferTest, EmptyUnusedUniformBuffer)
3663 {
3664     constexpr GLuint kBasicUBOIndex = 0;
3665     constexpr GLuint kEmptyUBOIndex = 1;
3666 
3667     // Create two UBOs. One is empty and the other is used.
3668     constexpr GLfloat basicUBOData[4] = {1.0, 2.0, 3.0, 4.0};
3669     GLBuffer basicUBO;
3670     glBindBuffer(GL_UNIFORM_BUFFER, basicUBO);
3671     glBufferData(GL_UNIFORM_BUFFER, sizeof(basicUBOData), basicUBOData, GL_STATIC_READ);
3672     glBindBufferBase(GL_UNIFORM_BUFFER, kBasicUBOIndex, basicUBO);
3673 
3674     GLBuffer emptyUBO;
3675     glBindBufferBase(GL_UNIFORM_BUFFER, kEmptyUBOIndex, emptyUBO);
3676 
3677     // Create a simple UBO program.
3678     constexpr char kFS[] = R"(#version 300 es
3679 precision mediump float;
3680 uniform basicBlock {
3681     vec4 basicVec4;
3682 };
3683 
3684 out vec4 outColor;
3685 
3686 void main() {
3687    if (basicVec4 == vec4(1, 2, 3, 4)) {
3688        outColor = vec4(0, 1, 0, 1);
3689    } else {
3690        outColor = vec4(1, 0, 0, 1);
3691    }
3692 })";
3693 
3694     // Draw and check result. Should not crash.
3695     ANGLE_GL_PROGRAM(uboProgram, essl3_shaders::vs::Simple(), kFS);
3696     drawQuad(uboProgram, essl1_shaders::PositionAttrib(), 0.5f, 1.0f);
3697     EXPECT_GL_NO_ERROR();
3698     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3699 }
3700 
3701 // Calling BufferData and use it in a loop to force descriptorSet creation and destroy.
TEST_P(UniformBufferTest,BufferDataInLoop)3702 TEST_P(UniformBufferTest, BufferDataInLoop)
3703 {
3704     glClear(GL_COLOR_BUFFER_BIT);
3705 
3706     // Use large buffer size to get around suballocation, so that we will gets a new buffer with
3707     // bufferData call.
3708     static constexpr size_t kBufferSize = 4 * 1024 * 1024;
3709     std::vector<float> floatData;
3710     floatData.resize(kBufferSize / (sizeof(float)), 0.0f);
3711     floatData[0] = 0.5f;
3712     floatData[1] = 0.75f;
3713     floatData[2] = 0.25f;
3714     floatData[3] = 1.0f;
3715 
3716     GLTexture textures[2];
3717     GLFramebuffer fbos[2];
3718     for (int i = 0; i < 2; i++)
3719     {
3720         glBindTexture(GL_TEXTURE_2D, textures[i]);
3721         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 256, 256);
3722 
3723         glBindFramebuffer(GL_FRAMEBUFFER, fbos[i]);
3724         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[i], 0);
3725         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3726     }
3727 
3728     for (int loop = 0; loop < 10; loop++)
3729     {
3730         int i = loop & 0x1;
3731         // Switch FBO to get around deferred flush
3732         glBindFramebuffer(GL_FRAMEBUFFER, fbos[i]);
3733         glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
3734         glBufferData(GL_UNIFORM_BUFFER, kBufferSize, floatData.data(), GL_STATIC_DRAW);
3735 
3736         glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
3737         glUniformBlockBinding(mProgram, mUniformBufferIndex, 0);
3738         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
3739         glFlush();
3740     }
3741     ASSERT_GL_NO_ERROR();
3742     EXPECT_PIXEL_NEAR(0, 0, 128, 191, 64, 255, 1);
3743 }
3744 
3745 class UniformBufferMemoryTest : public UniformBufferTest
3746 {
3747   protected:
getPerfCounters()3748     angle::VulkanPerfCounters getPerfCounters()
3749     {
3750         if (mIndexMap.empty())
3751         {
3752             mIndexMap = BuildCounterNameToIndexMap();
3753         }
3754 
3755         return GetPerfCounters(mIndexMap);
3756     }
3757 
3758     CounterNameToIndexMap mIndexMap;
3759 };
3760 
3761 // Calling BufferData and drawing with it in a loop without glFlush() should still work. Driver is
3762 // supposedly to issue flush if needed.
TEST_P(UniformBufferMemoryTest,BufferDataInLoopManyTimes)3763 TEST_P(UniformBufferMemoryTest, BufferDataInLoopManyTimes)
3764 {
3765     GLPerfMonitor monitor;
3766     glBeginPerfMonitorAMD(monitor);
3767 
3768     // Run this test for Vulkan only.
3769     ANGLE_SKIP_TEST_IF(!IsVulkan());
3770     uint64_t expectedSubmitCalls = getPerfCounters().commandQueueSubmitCallsTotal + 1;
3771 
3772     glClear(GL_COLOR_BUFFER_BIT);
3773     constexpr size_t kBufferSize = 64 * 1024 * 1024;
3774     std::vector<float> floatData;
3775     floatData.resize(kBufferSize / (sizeof(float)), 0.0f);
3776     floatData[0] = 0.5f;
3777     floatData[1] = 0.75f;
3778     floatData[2] = 0.25f;
3779     floatData[3] = 1.0f;
3780 
3781     GLTexture texture;
3782     GLFramebuffer fbo;
3783 
3784     glBindTexture(GL_TEXTURE_2D, texture);
3785     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 256, 256);
3786 
3787     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3788     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3789     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3790 
3791     constexpr uint32_t kIterationCount = 4096;
3792     for (uint32_t loop = 0; loop < kIterationCount; loop++)
3793     {
3794         glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
3795         glBufferData(GL_UNIFORM_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW);
3796         glBufferSubData(GL_UNIFORM_BUFFER, 0, kBufferSize, floatData.data());
3797 
3798         glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
3799         glUniformBlockBinding(mProgram, mUniformBufferIndex, 0);
3800         drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
3801 
3802         if (getPerfCounters().commandQueueSubmitCallsTotal == expectedSubmitCalls)
3803         {
3804             break;
3805         }
3806     }
3807     glEndPerfMonitorAMD(monitor);
3808 
3809     EXPECT_EQ(getPerfCounters().commandQueueSubmitCallsTotal, expectedSubmitCalls);
3810     ASSERT_GL_NO_ERROR();
3811     EXPECT_PIXEL_NEAR(0, 0, 128, 191, 64, 255, 1);
3812 }
3813 
3814 class WebGL2UniformBufferTest : public UniformBufferTest
3815 {
3816   protected:
WebGL2UniformBufferTest()3817     WebGL2UniformBufferTest() { setWebGLCompatibilityEnabled(true); }
3818 };
3819 
3820 // Test that ANGLE handles used but unbound UBO. Assumes we are running on ANGLE and produce
3821 // optional but not mandatory errors.
TEST_P(WebGL2UniformBufferTest,ANGLEUnboundUniformBuffer)3822 TEST_P(WebGL2UniformBufferTest, ANGLEUnboundUniformBuffer)
3823 {
3824     glUniformBlockBinding(mProgram, mUniformBufferIndex, 0);
3825     glBindBufferBase(GL_UNIFORM_BUFFER, 0, 0);
3826     EXPECT_GL_NO_ERROR();
3827 
3828     drawQuad(mProgram, essl3_shaders::PositionAttrib(), 0.5f);
3829     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
3830 }
3831 
3832 // Compile uniform buffer with large array member.
TEST_P(WebGL2UniformBufferTest,LargeArrayOfStructs)3833 TEST_P(WebGL2UniformBufferTest, LargeArrayOfStructs)
3834 {
3835     constexpr char kVertexShader[] = R"(
3836         struct InstancingData
3837         {
3838             vec4 transformation;
3839         };
3840 
3841         layout(std140) uniform InstanceBlock
3842         {
3843             InstancingData instances[MAX_INSTANCE_COUNT];
3844         };
3845 
3846         void main()
3847         {
3848             gl_Position = vec4(1.0) * instances[gl_InstanceID].transformation[0];
3849         })";
3850 
3851     constexpr char kFragmentShader[] = R"(#version 300 es
3852         precision mediump float;
3853         out vec4 outFragColor;
3854         void main()
3855         {
3856             outFragColor = vec4(0.0);
3857         })";
3858 
3859     int maxUniformBlockSize;
3860     glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize);
3861 
3862     std::string vs = "#version 300 es\n#define MAX_INSTANCE_COUNT " +
3863                      std::to_string(maxUniformBlockSize / 16) + kVertexShader;
3864 
3865     ANGLE_GL_PROGRAM(program, vs.c_str(), kFragmentShader);
3866 }
3867 
3868 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UniformBufferTest);
3869 ANGLE_INSTANTIATE_TEST_ES3(UniformBufferTest);
3870 
3871 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UniformBlockWithOneLargeArrayMemberTest);
3872 ANGLE_INSTANTIATE_TEST_ES3(UniformBlockWithOneLargeArrayMemberTest);
3873 
3874 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UniformBufferTest31);
3875 ANGLE_INSTANTIATE_TEST_ES31(UniformBufferTest31);
3876 
3877 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UniformBufferMemoryTest);
3878 ANGLE_INSTANTIATE_TEST_ES3(UniformBufferMemoryTest);
3879 
3880 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGL2UniformBufferTest);
3881 ANGLE_INSTANTIATE_TEST_ES3(WebGL2UniformBufferTest);
3882 
3883 }  // namespace
3884