xref: /aosp_15_r20/external/angle/src/tests/gl_tests/VertexAttributeTest.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 #include "anglebase/numerics/safe_conversions.h"
7 #include "common/mathutil.h"
8 #include "test_utils/ANGLETest.h"
9 #include "test_utils/gl_raii.h"
10 #include "util/random_utils.h"
11 
12 using namespace angle;
13 
14 namespace
15 {
16 
TypeStride(GLenum attribType)17 GLsizei TypeStride(GLenum attribType)
18 {
19     switch (attribType)
20     {
21         case GL_UNSIGNED_BYTE:
22         case GL_BYTE:
23             return 1;
24         case GL_UNSIGNED_SHORT:
25         case GL_SHORT:
26         case GL_HALF_FLOAT:
27         case GL_HALF_FLOAT_OES:
28             return 2;
29         case GL_UNSIGNED_INT:
30         case GL_INT:
31         case GL_FLOAT:
32         case GL_UNSIGNED_INT_10_10_10_2_OES:
33         case GL_INT_10_10_10_2_OES:
34             return 4;
35         default:
36             EXPECT_TRUE(false);
37             return 0;
38     }
39 }
40 
41 template <typename T>
Normalize(T value)42 GLfloat Normalize(T value)
43 {
44     static_assert(std::is_integral<T>::value, "Integer required.");
45     if (std::is_signed<T>::value)
46     {
47         typedef typename std::make_unsigned<T>::type unsigned_type;
48         return (2.0f * static_cast<GLfloat>(value) + 1.0f) /
49                static_cast<GLfloat>(std::numeric_limits<unsigned_type>::max());
50     }
51     else
52     {
53         return static_cast<GLfloat>(value) / static_cast<GLfloat>(std::numeric_limits<T>::max());
54     }
55 }
56 
57 // Normalization for each channel of signed/unsigned 10_10_10_2 types
58 template <typename T>
Normalize10(T value)59 GLfloat Normalize10(T value)
60 {
61     static_assert(std::is_integral<T>::value, "Integer required.");
62     GLfloat floatOutput;
63     if (std::is_signed<T>::value)
64     {
65         const uint32_t signMask     = 0x200;       // 1 set at the 9th bit
66         const uint32_t negativeMask = 0xFFFFFC00;  // All bits from 10 to 31 set to 1
67 
68         if (value & signMask)
69         {
70             int negativeNumber = value | negativeMask;
71             floatOutput        = static_cast<GLfloat>(negativeNumber);
72         }
73         else
74         {
75             floatOutput = static_cast<GLfloat>(value);
76         }
77 
78         const int32_t maxValue = 0x1FF;       // 1 set in bits 0 through 8
79         const int32_t minValue = 0xFFFFFE01;  // Inverse of maxValue
80 
81         // A 10-bit two's complement number has the possibility of being minValue - 1 but
82         // OpenGL's normalization rules dictate that it should be clamped to minValue in
83         // this case.
84         if (floatOutput < minValue)
85             floatOutput = minValue;
86 
87         const int32_t halfRange = (maxValue - minValue) >> 1;
88         floatOutput             = ((floatOutput - minValue) / halfRange) - 1.0f;
89     }
90     else
91     {
92         const GLfloat maxValue = 1023.0f;  // 1 set in bits 0 through 9
93         floatOutput            = static_cast<GLfloat>(value) / maxValue;
94     }
95     return floatOutput;
96 }
97 
98 template <typename T>
Normalize2(T value)99 GLfloat Normalize2(T value)
100 {
101     static_assert(std::is_integral<T>::value, "Integer required.");
102     if (std::is_signed<T>::value)
103     {
104         GLfloat outputValue = static_cast<float>(value) / 1.0f;
105         outputValue         = (outputValue >= -1.0f) ? (outputValue) : (-1.0f);
106         return outputValue;
107     }
108     else
109     {
110         return static_cast<float>(value) / 3.0f;
111     }
112 }
113 
114 template <typename DestT, typename SrcT>
Pack1010102(std::array<SrcT,4> input)115 DestT Pack1010102(std::array<SrcT, 4> input)
116 {
117     static_assert(std::is_integral<SrcT>::value, "Integer required.");
118     static_assert(std::is_integral<DestT>::value, "Integer required.");
119     static_assert(std::is_unsigned<SrcT>::value == std::is_unsigned<DestT>::value,
120                   "Signedness should be equal.");
121     DestT rOut, gOut, bOut, aOut;
122     rOut = static_cast<DestT>(input[0]);
123     gOut = static_cast<DestT>(input[1]);
124     bOut = static_cast<DestT>(input[2]);
125     aOut = static_cast<DestT>(input[3]);
126 
127     if (std::is_unsigned<SrcT>::value)
128     {
129         return rOut << 22 | gOut << 12 | bOut << 2 | aOut;
130     }
131     else
132     {
133         // Need to apply bit mask to account for sign extension
134         return (0xFFC00000u & rOut << 22) | (0x003FF000u & gOut << 12) | (0x00000FFCu & bOut << 2) |
135                (0x00000003u & aOut);
136     }
137 }
138 
139 class VertexAttributeTest : public ANGLETest<>
140 {
141   protected:
VertexAttributeTest()142     VertexAttributeTest() : mProgram(0), mTestAttrib(-1), mExpectedAttrib(-1), mBuffer(0)
143     {
144         setWindowWidth(128);
145         setWindowHeight(128);
146         setConfigRedBits(8);
147         setConfigGreenBits(8);
148         setConfigBlueBits(8);
149         setConfigAlphaBits(8);
150         setConfigDepthBits(24);
151     }
152 
153     enum class Source
154     {
155         BUFFER,
156         IMMEDIATE,
157     };
158 
159     struct TestData final : private angle::NonCopyable
160     {
TestData__anon8ff86acd0111::VertexAttributeTest::TestData161         TestData(GLenum typeIn,
162                  GLboolean normalizedIn,
163                  Source sourceIn,
164                  const void *inputDataIn,
165                  const GLfloat *expectedDataIn)
166             : type(typeIn),
167               normalized(normalizedIn),
168               bufferOffset(0),
169               source(sourceIn),
170               inputData(inputDataIn),
171               expectedData(expectedDataIn),
172               clearBeforeDraw(false)
173         {}
174 
175         GLenum type;
176         GLboolean normalized;
177         size_t bufferOffset;
178         Source source;
179 
180         const void *inputData;
181         const GLfloat *expectedData;
182 
183         bool clearBeforeDraw;
184     };
185 
setupTest(const TestData & test,GLint typeSize)186     void setupTest(const TestData &test, GLint typeSize)
187     {
188         if (mProgram == 0)
189         {
190             initBasicProgram();
191         }
192 
193         if (test.source == Source::BUFFER)
194         {
195             GLsizei dataSize = kVertexCount * TypeStride(test.type);
196             glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
197             glBufferData(GL_ARRAY_BUFFER, dataSize, test.inputData, GL_STATIC_DRAW);
198             glVertexAttribPointer(mTestAttrib, typeSize, test.type, test.normalized, 0,
199                                   reinterpret_cast<void *>(test.bufferOffset));
200             glBindBuffer(GL_ARRAY_BUFFER, 0);
201         }
202         else
203         {
204             ASSERT_EQ(Source::IMMEDIATE, test.source);
205             glBindBuffer(GL_ARRAY_BUFFER, 0);
206             glVertexAttribPointer(mTestAttrib, typeSize, test.type, test.normalized, 0,
207                                   test.inputData);
208         }
209 
210         glVertexAttribPointer(mExpectedAttrib, typeSize, GL_FLOAT, GL_FALSE, 0, test.expectedData);
211 
212         glEnableVertexAttribArray(mTestAttrib);
213         glEnableVertexAttribArray(mExpectedAttrib);
214     }
215 
checkPixels()216     void checkPixels()
217     {
218         GLint viewportSize[4];
219         glGetIntegerv(GL_VIEWPORT, viewportSize);
220 
221         GLint midPixelX = (viewportSize[0] + viewportSize[2]) / 2;
222         GLint midPixelY = (viewportSize[1] + viewportSize[3]) / 2;
223 
224         // We need to offset our checks from triangle edges to ensure we don't fall on a single tri
225         // Avoid making assumptions of drawQuad with four checks to check the four possible tri
226         // regions
227         EXPECT_PIXEL_EQ((midPixelX + viewportSize[0]) / 2, midPixelY, 255, 255, 255, 255);
228         EXPECT_PIXEL_EQ((midPixelX + viewportSize[2]) / 2, midPixelY, 255, 255, 255, 255);
229         EXPECT_PIXEL_EQ(midPixelX, (midPixelY + viewportSize[1]) / 2, 255, 255, 255, 255);
230         EXPECT_PIXEL_EQ(midPixelX, (midPixelY + viewportSize[3]) / 2, 255, 255, 255, 255);
231     }
232 
checkPixelsUnEqual()233     void checkPixelsUnEqual()
234     {
235         GLint viewportSize[4];
236         glGetIntegerv(GL_VIEWPORT, viewportSize);
237 
238         GLint midPixelX = (viewportSize[0] + viewportSize[2]) / 2;
239         GLint midPixelY = (viewportSize[1] + viewportSize[3]) / 2;
240 
241         // We need to offset our checks from triangle edges to ensure we don't fall on a single tri
242         // Avoid making assumptions of drawQuad with four checks to check the four possible tri
243         // regions
244         EXPECT_PIXEL_NE((midPixelX + viewportSize[0]) / 2, midPixelY, 255, 255, 255, 255);
245         EXPECT_PIXEL_NE((midPixelX + viewportSize[2]) / 2, midPixelY, 255, 255, 255, 255);
246         EXPECT_PIXEL_NE(midPixelX, (midPixelY + viewportSize[1]) / 2, 255, 255, 255, 255);
247         EXPECT_PIXEL_NE(midPixelX, (midPixelY + viewportSize[3]) / 2, 255, 255, 255, 255);
248     }
249 
runTest(const TestData & test)250     void runTest(const TestData &test) { runTest(test, true); }
251 
runTest(const TestData & test,bool checkPixelEqual)252     void runTest(const TestData &test, bool checkPixelEqual)
253     {
254         // TODO(geofflang): Figure out why this is broken on AMD OpenGL
255         ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
256 
257         for (GLint i = 0; i < 4; i++)
258         {
259             GLint typeSize = i + 1;
260             setupTest(test, typeSize);
261 
262             if (test.clearBeforeDraw)
263             {
264                 glClear(GL_COLOR_BUFFER_BIT);
265             }
266 
267             drawQuad(mProgram, "position", 0.5f);
268 
269             glDisableVertexAttribArray(mTestAttrib);
270             glDisableVertexAttribArray(mExpectedAttrib);
271 
272             if (checkPixelEqual)
273             {
274                 checkPixels();
275             }
276             else
277             {
278                 checkPixelsUnEqual();
279             }
280         }
281     }
282 
testSetUp()283     void testSetUp() override
284     {
285         glClearColor(0, 0, 0, 0);
286         glClearDepthf(0.0);
287         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
288 
289         glDisable(GL_DEPTH_TEST);
290 
291         glGenBuffers(1, &mBuffer);
292     }
293 
testTearDown()294     void testTearDown() override
295     {
296         glDeleteProgram(mProgram);
297         glDeleteBuffers(1, &mBuffer);
298     }
299 
compileMultiAttribProgram(GLint attribCount)300     GLuint compileMultiAttribProgram(GLint attribCount)
301     {
302         std::stringstream shaderStream;
303 
304         shaderStream << "attribute mediump vec4 position;" << std::endl;
305         for (GLint attribIndex = 0; attribIndex < attribCount; ++attribIndex)
306         {
307             shaderStream << "attribute float a" << attribIndex << ";" << std::endl;
308         }
309         shaderStream << "varying mediump float color;" << std::endl
310                      << "void main() {" << std::endl
311                      << "  gl_Position = position;" << std::endl
312                      << "  color = 0.0;" << std::endl;
313         for (GLint attribIndex = 0; attribIndex < attribCount; ++attribIndex)
314         {
315             shaderStream << "  color += a" << attribIndex << ";" << std::endl;
316         }
317         shaderStream << "}" << std::endl;
318 
319         constexpr char kFS[] =
320             "varying mediump float color;\n"
321             "void main(void)\n"
322             "{\n"
323             "    gl_FragColor = vec4(color, 0.0, 0.0, 1.0);\n"
324             "}\n";
325 
326         return CompileProgram(shaderStream.str().c_str(), kFS);
327     }
328 
setupMultiAttribs(GLuint program,GLint attribCount,GLfloat value)329     void setupMultiAttribs(GLuint program, GLint attribCount, GLfloat value)
330     {
331         glUseProgram(program);
332         for (GLint attribIndex = 0; attribIndex < attribCount; ++attribIndex)
333         {
334             std::stringstream attribStream;
335             attribStream << "a" << attribIndex;
336             GLint location = glGetAttribLocation(program, attribStream.str().c_str());
337             ASSERT_NE(-1, location);
338             glVertexAttrib1f(location, value);
339             glDisableVertexAttribArray(location);
340         }
341     }
342 
initBasicProgram()343     void initBasicProgram()
344     {
345         constexpr char kVS[] =
346             "attribute mediump vec4 position;\n"
347             "attribute highp vec4 test;\n"
348             "attribute highp vec4 expected;\n"
349             "varying mediump vec4 color;\n"
350             "void main(void)\n"
351             "{\n"
352             "    gl_Position = position;\n"
353             "    vec4 threshold = max(abs(expected) * 0.01, 1.0 / 64.0);\n"
354             "    color = vec4(lessThanEqual(abs(test - expected), threshold));\n"
355             "}\n";
356 
357         constexpr char kFS[] =
358             "varying mediump vec4 color;\n"
359             "void main(void)\n"
360             "{\n"
361             "    gl_FragColor = color;\n"
362             "}\n";
363 
364         mProgram = CompileProgram(kVS, kFS);
365         ASSERT_NE(0u, mProgram);
366 
367         mTestAttrib = glGetAttribLocation(mProgram, "test");
368         ASSERT_NE(-1, mTestAttrib);
369         mExpectedAttrib = glGetAttribLocation(mProgram, "expected");
370         ASSERT_NE(-1, mExpectedAttrib);
371 
372         glUseProgram(mProgram);
373     }
374 
375     static constexpr size_t kVertexCount = 24;
376 
InitTestData(std::array<GLfloat,kVertexCount> & inputData,std::array<GLfloat,kVertexCount> & expectedData)377     static void InitTestData(std::array<GLfloat, kVertexCount> &inputData,
378                              std::array<GLfloat, kVertexCount> &expectedData)
379     {
380         for (size_t count = 0; count < kVertexCount; ++count)
381         {
382             inputData[count]    = static_cast<GLfloat>(count);
383             expectedData[count] = inputData[count];
384         }
385     }
386 
InitQuadVertexBuffer(GLBuffer * buffer)387     static void InitQuadVertexBuffer(GLBuffer *buffer)
388     {
389         auto quadVertices = GetQuadVertices();
390         GLsizei quadVerticesSize =
391             static_cast<GLsizei>(quadVertices.size() * sizeof(quadVertices[0]));
392 
393         glBindBuffer(GL_ARRAY_BUFFER, *buffer);
394         glBufferData(GL_ARRAY_BUFFER, quadVerticesSize, nullptr, GL_STATIC_DRAW);
395         glBufferSubData(GL_ARRAY_BUFFER, 0, quadVerticesSize, quadVertices.data());
396     }
397 
InitQuadPlusOneVertexBuffer(GLBuffer * buffer)398     static void InitQuadPlusOneVertexBuffer(GLBuffer *buffer)
399     {
400         auto quadVertices = GetQuadVertices();
401         GLsizei quadVerticesSize =
402             static_cast<GLsizei>(quadVertices.size() * sizeof(quadVertices[0]));
403 
404         glBindBuffer(GL_ARRAY_BUFFER, *buffer);
405         glBufferData(GL_ARRAY_BUFFER, quadVerticesSize + sizeof(Vector3), nullptr, GL_STATIC_DRAW);
406         glBufferSubData(GL_ARRAY_BUFFER, 0, quadVerticesSize, quadVertices.data());
407         glBufferSubData(GL_ARRAY_BUFFER, quadVerticesSize, sizeof(Vector3), &quadVertices[0]);
408     }
409 
410     GLuint mProgram;
411     GLint mTestAttrib;
412     GLint mExpectedAttrib;
413     GLuint mBuffer;
414 };
415 
TEST_P(VertexAttributeTest,UnsignedByteUnnormalized)416 TEST_P(VertexAttributeTest, UnsignedByteUnnormalized)
417 {
418     std::array<GLubyte, kVertexCount> inputData = {
419         {0, 1, 2, 3, 4, 5, 6, 7, 125, 126, 127, 128, 129, 250, 251, 252, 253, 254, 255}};
420     std::array<GLfloat, kVertexCount> expectedData;
421     for (size_t i = 0; i < kVertexCount; i++)
422     {
423         expectedData[i] = inputData[i];
424     }
425 
426     TestData data(GL_UNSIGNED_BYTE, GL_FALSE, Source::IMMEDIATE, inputData.data(),
427                   expectedData.data());
428     runTest(data);
429 }
430 
TEST_P(VertexAttributeTest,UnsignedByteNormalized)431 TEST_P(VertexAttributeTest, UnsignedByteNormalized)
432 {
433     std::array<GLubyte, kVertexCount> inputData = {
434         {0, 1, 2, 3, 4, 5, 6, 7, 125, 126, 127, 128, 129, 250, 251, 252, 253, 254, 255}};
435     std::array<GLfloat, kVertexCount> expectedData;
436     for (size_t i = 0; i < kVertexCount; i++)
437     {
438         expectedData[i] = Normalize(inputData[i]);
439     }
440 
441     TestData data(GL_UNSIGNED_BYTE, GL_TRUE, Source::IMMEDIATE, inputData.data(),
442                   expectedData.data());
443     runTest(data);
444 }
445 
TEST_P(VertexAttributeTest,ByteUnnormalized)446 TEST_P(VertexAttributeTest, ByteUnnormalized)
447 {
448     std::array<GLbyte, kVertexCount> inputData = {
449         {0, 1, 2, 3, 4, -1, -2, -3, -4, 125, 126, 127, -128, -127, -126}};
450     std::array<GLfloat, kVertexCount> expectedData;
451     for (size_t i = 0; i < kVertexCount; i++)
452     {
453         expectedData[i] = inputData[i];
454     }
455 
456     TestData data(GL_BYTE, GL_FALSE, Source::IMMEDIATE, inputData.data(), expectedData.data());
457     runTest(data);
458 }
459 
TEST_P(VertexAttributeTest,ByteNormalized)460 TEST_P(VertexAttributeTest, ByteNormalized)
461 {
462     std::array<GLbyte, kVertexCount> inputData = {
463         {0, 1, 2, 3, 4, -1, -2, -3, -4, 125, 126, 127, -128, -127, -126}};
464     std::array<GLfloat, kVertexCount> expectedData;
465     for (size_t i = 0; i < kVertexCount; i++)
466     {
467         expectedData[i] = Normalize(inputData[i]);
468     }
469 
470     TestData data(GL_BYTE, GL_TRUE, Source::IMMEDIATE, inputData.data(), expectedData.data());
471     runTest(data);
472 }
473 
TEST_P(VertexAttributeTest,UnsignedShortUnnormalized)474 TEST_P(VertexAttributeTest, UnsignedShortUnnormalized)
475 {
476     std::array<GLushort, kVertexCount> inputData = {
477         {0, 1, 2, 3, 254, 255, 256, 32766, 32767, 32768, 65533, 65534, 65535}};
478     std::array<GLfloat, kVertexCount> expectedData;
479     for (size_t i = 0; i < kVertexCount; i++)
480     {
481         expectedData[i] = inputData[i];
482     }
483 
484     TestData data(GL_UNSIGNED_SHORT, GL_FALSE, Source::IMMEDIATE, inputData.data(),
485                   expectedData.data());
486     runTest(data);
487 }
488 
TEST_P(VertexAttributeTest,UnsignedShortNormalized)489 TEST_P(VertexAttributeTest, UnsignedShortNormalized)
490 {
491     std::array<GLushort, kVertexCount> inputData = {
492         {0, 1, 2, 3, 254, 255, 256, 32766, 32767, 32768, 65533, 65534, 65535}};
493     std::array<GLfloat, kVertexCount> expectedData;
494     for (size_t i = 0; i < kVertexCount; i++)
495     {
496         expectedData[i] = Normalize(inputData[i]);
497     }
498 
499     TestData data(GL_UNSIGNED_SHORT, GL_TRUE, Source::IMMEDIATE, inputData.data(),
500                   expectedData.data());
501     runTest(data);
502 }
503 
TEST_P(VertexAttributeTest,ShortUnnormalized)504 TEST_P(VertexAttributeTest, ShortUnnormalized)
505 {
506     std::array<GLshort, kVertexCount> inputData = {
507         {0, 1, 2, 3, -1, -2, -3, -4, 32766, 32767, -32768, -32767, -32766}};
508     std::array<GLfloat, kVertexCount> expectedData;
509     for (size_t i = 0; i < kVertexCount; i++)
510     {
511         expectedData[i] = inputData[i];
512     }
513 
514     TestData data(GL_SHORT, GL_FALSE, Source::IMMEDIATE, inputData.data(), expectedData.data());
515     runTest(data);
516 }
517 
TEST_P(VertexAttributeTest,ShortNormalized)518 TEST_P(VertexAttributeTest, ShortNormalized)
519 {
520     std::array<GLshort, kVertexCount> inputData = {
521         {0, 1, 2, 3, -1, -2, -3, -4, 32766, 32767, -32768, -32767, -32766}};
522     std::array<GLfloat, kVertexCount> expectedData;
523     for (size_t i = 0; i < kVertexCount; i++)
524     {
525         expectedData[i] = Normalize(inputData[i]);
526     }
527 
528     TestData data(GL_SHORT, GL_TRUE, Source::IMMEDIATE, inputData.data(), expectedData.data());
529     runTest(data);
530 }
531 
532 // Verify that vertex data is updated correctly when using a float/half-float client memory pointer.
TEST_P(VertexAttributeTest,HalfFloatClientMemoryPointer)533 TEST_P(VertexAttributeTest, HalfFloatClientMemoryPointer)
534 {
535     std::array<GLhalf, kVertexCount> inputData;
536     std::array<GLfloat, kVertexCount> expectedData = {
537         {0.f, 1.5f, 2.3f, 3.2f, -1.8f, -2.2f, -3.9f, -4.f, 34.5f, 32.2f, -78.8f, -77.4f, -76.1f}};
538 
539     for (size_t i = 0; i < kVertexCount; i++)
540     {
541         inputData[i] = gl::float32ToFloat16(expectedData[i]);
542     }
543 
544     // If the extension is enabled run the test on all contexts
545     if (IsGLExtensionEnabled("GL_OES_vertex_half_float"))
546     {
547         TestData imediateData(GL_HALF_FLOAT_OES, GL_FALSE, Source::IMMEDIATE, inputData.data(),
548                               expectedData.data());
549         runTest(imediateData);
550     }
551     // Otherwise run the test only if it is an ES3 context
552     else if (getClientMajorVersion() >= 3)
553     {
554         TestData imediateData(GL_HALF_FLOAT, GL_FALSE, Source::IMMEDIATE, inputData.data(),
555                               expectedData.data());
556         runTest(imediateData);
557     }
558 }
559 
560 // Verify that vertex data is updated correctly when using a float/half-float buffer.
TEST_P(VertexAttributeTest,HalfFloatBuffer)561 TEST_P(VertexAttributeTest, HalfFloatBuffer)
562 {
563     std::array<GLhalf, kVertexCount> inputData;
564     std::array<GLfloat, kVertexCount> expectedData = {
565         {0.f, 1.5f, 2.3f, 3.2f, -1.8f, -2.2f, -3.9f, -4.f, 34.5f, 32.2f, -78.8f, -77.4f, -76.1f}};
566 
567     for (size_t i = 0; i < kVertexCount; i++)
568     {
569         inputData[i] = gl::float32ToFloat16(expectedData[i]);
570     }
571 
572     // If the extension is enabled run the test on all contexts
573     if (IsGLExtensionEnabled("GL_OES_vertex_half_float"))
574     {
575         TestData bufferData(GL_HALF_FLOAT_OES, GL_FALSE, Source::BUFFER, inputData.data(),
576                             expectedData.data());
577         runTest(bufferData);
578     }
579     // Otherwise run the test only if it is an ES3 context
580     else if (getClientMajorVersion() >= 3)
581     {
582         TestData bufferData(GL_HALF_FLOAT, GL_FALSE, Source::BUFFER, inputData.data(),
583                             expectedData.data());
584         runTest(bufferData);
585     }
586 }
587 
588 // Verify that using the same client memory pointer in different format won't mess up the draw.
TEST_P(VertexAttributeTest,UsingDifferentFormatAndSameClientMemoryPointer)589 TEST_P(VertexAttributeTest, UsingDifferentFormatAndSameClientMemoryPointer)
590 {
591     std::array<GLshort, kVertexCount> inputData = {
592         {0, 1, 2, 3, -1, -2, -3, -4, 32766, 32767, -32768, -32767, -32766}};
593 
594     std::array<GLfloat, kVertexCount> unnormalizedExpectedData;
595     for (size_t i = 0; i < kVertexCount; i++)
596     {
597         unnormalizedExpectedData[i] = inputData[i];
598     }
599 
600     TestData unnormalizedData(GL_SHORT, GL_FALSE, Source::IMMEDIATE, inputData.data(),
601                               unnormalizedExpectedData.data());
602     runTest(unnormalizedData);
603 
604     std::array<GLfloat, kVertexCount> normalizedExpectedData;
605     for (size_t i = 0; i < kVertexCount; i++)
606     {
607         inputData[i]              = -inputData[i];
608         normalizedExpectedData[i] = Normalize(inputData[i]);
609     }
610 
611     TestData normalizedData(GL_SHORT, GL_TRUE, Source::IMMEDIATE, inputData.data(),
612                             normalizedExpectedData.data());
613     runTest(normalizedData);
614 }
615 
616 // Verify that vertex format is updated correctly when the client memory pointer is same.
TEST_P(VertexAttributeTest,NegativeUsingDifferentFormatAndSameClientMemoryPointer)617 TEST_P(VertexAttributeTest, NegativeUsingDifferentFormatAndSameClientMemoryPointer)
618 {
619     std::array<GLshort, kVertexCount> inputData = {
620         {0, 1, 2, 3, -1, -2, -3, -4, 32766, 32767, -32768, -32767, -32766}};
621 
622     std::array<GLfloat, kVertexCount> unnormalizedExpectedData;
623     for (size_t i = 0; i < kVertexCount; i++)
624     {
625         unnormalizedExpectedData[i] = inputData[i];
626     }
627 
628     // Use unnormalized short as the format of the data in client memory pointer in the first draw.
629     TestData unnormalizedData(GL_SHORT, GL_FALSE, Source::IMMEDIATE, inputData.data(),
630                               unnormalizedExpectedData.data());
631     runTest(unnormalizedData);
632 
633     // Use normalized short as the format of the data in client memory pointer in the second draw,
634     // but mExpectedAttrib is the same as the first draw.
635     TestData normalizedData(GL_SHORT, GL_TRUE, Source::IMMEDIATE, inputData.data(),
636                             unnormalizedExpectedData.data());
637     runTest(normalizedData, false);
638 }
639 
640 // Verify that using different vertex format and same buffer won't mess up the draw.
TEST_P(VertexAttributeTest,UsingDifferentFormatAndSameBuffer)641 TEST_P(VertexAttributeTest, UsingDifferentFormatAndSameBuffer)
642 {
643     std::array<GLshort, kVertexCount> inputData = {
644         {0, 1, 2, 3, -1, -2, -3, -4, 32766, 32767, -32768, -32767, -32766}};
645 
646     std::array<GLfloat, kVertexCount> unnormalizedExpectedData;
647     std::array<GLfloat, kVertexCount> normalizedExpectedData;
648     for (size_t i = 0; i < kVertexCount; i++)
649     {
650         unnormalizedExpectedData[i] = inputData[i];
651         normalizedExpectedData[i]   = Normalize(inputData[i]);
652     }
653 
654     // Use unnormalized short as the format of the data in mBuffer in the first draw.
655     TestData unnormalizedData(GL_SHORT, GL_FALSE, Source::BUFFER, inputData.data(),
656                               unnormalizedExpectedData.data());
657     runTest(unnormalizedData);
658 
659     // Use normalized short as the format of the data in mBuffer in the second draw.
660     TestData normalizedData(GL_SHORT, GL_TRUE, Source::BUFFER, inputData.data(),
661                             normalizedExpectedData.data());
662     runTest(normalizedData);
663 }
664 
665 // Verify that vertex format is updated correctly when the buffer is same.
TEST_P(VertexAttributeTest,NegativeUsingDifferentFormatAndSameBuffer)666 TEST_P(VertexAttributeTest, NegativeUsingDifferentFormatAndSameBuffer)
667 {
668     std::array<GLshort, kVertexCount> inputData = {
669         {0, 1, 2, 3, -1, -2, -3, -4, 32766, 32767, -32768, -32767, -32766}};
670 
671     std::array<GLfloat, kVertexCount> unnormalizedExpectedData;
672     for (size_t i = 0; i < kVertexCount; i++)
673     {
674         unnormalizedExpectedData[i] = inputData[i];
675     }
676 
677     // Use unnormalized short as the format of the data in mBuffer in the first draw.
678     TestData unnormalizedData(GL_SHORT, GL_FALSE, Source::BUFFER, inputData.data(),
679                               unnormalizedExpectedData.data());
680     runTest(unnormalizedData);
681 
682     // Use normalized short as the format of the data in mBuffer in the second draw, but
683     // mExpectedAttrib is the same as the first draw.
684     TestData normalizedData(GL_SHORT, GL_TRUE, Source::BUFFER, inputData.data(),
685                             unnormalizedExpectedData.data());
686 
687     // The check should fail because the test data is changed while the expected data is the same.
688     runTest(normalizedData, false);
689 }
690 
691 // Verify that mixed using buffer and client memory pointer won't mess up the draw.
TEST_P(VertexAttributeTest,MixedUsingBufferAndClientMemoryPointer)692 TEST_P(VertexAttributeTest, MixedUsingBufferAndClientMemoryPointer)
693 {
694     std::array<GLshort, kVertexCount> inputData = {
695         {0, 1, 2, 3, -1, -2, -3, -4, 32766, 32767, -32768, -32767, -32766}};
696 
697     std::array<GLfloat, kVertexCount> unnormalizedExpectedData;
698     std::array<GLfloat, kVertexCount> normalizedExpectedData;
699     for (size_t i = 0; i < kVertexCount; i++)
700     {
701         unnormalizedExpectedData[i] = inputData[i];
702         normalizedExpectedData[i]   = Normalize(inputData[i]);
703     }
704 
705     TestData unnormalizedData(GL_SHORT, GL_FALSE, Source::IMMEDIATE, inputData.data(),
706                               unnormalizedExpectedData.data());
707     runTest(unnormalizedData);
708 
709     TestData unnormalizedBufferData(GL_SHORT, GL_FALSE, Source::BUFFER, inputData.data(),
710                                     unnormalizedExpectedData.data());
711     runTest(unnormalizedBufferData);
712 
713     TestData normalizedData(GL_SHORT, GL_TRUE, Source::IMMEDIATE, inputData.data(),
714                             normalizedExpectedData.data());
715     runTest(normalizedData);
716 }
717 
718 // Verify signed unnormalized INT_10_10_10_2 vertex type
TEST_P(VertexAttributeTest,SignedPacked1010102ExtensionUnnormalized)719 TEST_P(VertexAttributeTest, SignedPacked1010102ExtensionUnnormalized)
720 {
721     std::string extensionList(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)));
722     ANGLE_SKIP_TEST_IF((extensionList.find("OES_vertex_type_10_10_10_2") == std::string::npos));
723 
724     // RGB channels are 10-bits, alpha is 2-bits
725     std::array<std::array<GLshort, 4>, kVertexCount / 4> unpackedInput = {{{0, 1, 2, 0},
726                                                                            {254, 255, 256, 1},
727                                                                            {256, 255, 254, -2},
728                                                                            {511, 510, 509, -1},
729                                                                            {-512, -511, -500, -2},
730                                                                            {-1, -2, -3, 1}}};
731 
732     std::array<GLint, kVertexCount> packedInput;
733     std::array<GLfloat, kVertexCount> expectedTypeSize4;
734     std::array<GLfloat, kVertexCount> expectedTypeSize3;
735 
736     for (size_t i = 0; i < kVertexCount / 4; i++)
737     {
738         packedInput[i] = Pack1010102<GLint, GLshort>(unpackedInput[i]);
739 
740         expectedTypeSize3[i * 3 + 0] = expectedTypeSize4[i * 4 + 0] = unpackedInput[i][0];
741         expectedTypeSize3[i * 3 + 1] = expectedTypeSize4[i * 4 + 1] = unpackedInput[i][1];
742         expectedTypeSize3[i * 3 + 2] = expectedTypeSize4[i * 4 + 2] = unpackedInput[i][2];
743 
744         // when the type size is 3, alpha will be 1.0f by GLES driver
745         expectedTypeSize4[i * 4 + 3] = unpackedInput[i][3];
746     }
747 
748     TestData data4(GL_INT_10_10_10_2_OES, GL_FALSE, Source::IMMEDIATE, packedInput.data(),
749                    expectedTypeSize4.data());
750     TestData bufferedData4(GL_INT_10_10_10_2_OES, GL_FALSE, Source::BUFFER, packedInput.data(),
751                            expectedTypeSize4.data());
752     TestData data3(GL_INT_10_10_10_2_OES, GL_FALSE, Source::IMMEDIATE, packedInput.data(),
753                    expectedTypeSize3.data());
754     TestData bufferedData3(GL_INT_10_10_10_2_OES, GL_FALSE, Source::BUFFER, packedInput.data(),
755                            expectedTypeSize3.data());
756 
757     std::array<std::pair<const TestData &, GLint>, 4> dataSet = {
758         {{data4, 4}, {bufferedData4, 4}, {data3, 3}, {bufferedData3, 3}}};
759 
760     for (auto data : dataSet)
761     {
762         setupTest(data.first, data.second);
763         drawQuad(mProgram, "position", 0.5f);
764         glDisableVertexAttribArray(mTestAttrib);
765         glDisableVertexAttribArray(mExpectedAttrib);
766         checkPixels();
767     }
768 }
769 
770 // Verify signed normalized INT_10_10_10_2 vertex type
TEST_P(VertexAttributeTest,SignedPacked1010102ExtensionNormalized)771 TEST_P(VertexAttributeTest, SignedPacked1010102ExtensionNormalized)
772 {
773     std::string extensionList(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)));
774     ANGLE_SKIP_TEST_IF((extensionList.find("OES_vertex_type_10_10_10_2") == std::string::npos));
775 
776     // RGB channels are 10-bits, alpha is 2-bits
777     std::array<std::array<GLshort, 4>, kVertexCount / 4> unpackedInput = {{{0, 1, 2, 0},
778                                                                            {254, 255, 256, 1},
779                                                                            {256, 255, 254, -2},
780                                                                            {511, 510, 509, -1},
781                                                                            {-512, -511, -500, -2},
782                                                                            {-1, -2, -3, 1}}};
783     std::array<GLint, kVertexCount> packedInput;
784     std::array<GLfloat, kVertexCount> expectedNormalizedTypeSize4;
785     std::array<GLfloat, kVertexCount> expectedNormalizedTypeSize3;
786 
787     for (size_t i = 0; i < kVertexCount / 4; i++)
788     {
789         packedInput[i] = Pack1010102<GLint, GLshort>(unpackedInput[i]);
790 
791         expectedNormalizedTypeSize3[i * 3 + 0] = expectedNormalizedTypeSize4[i * 4 + 0] =
792             Normalize10<GLshort>(unpackedInput[i][0]);
793         expectedNormalizedTypeSize3[i * 3 + 1] = expectedNormalizedTypeSize4[i * 4 + 1] =
794             Normalize10<GLshort>(unpackedInput[i][1]);
795         expectedNormalizedTypeSize3[i * 3 + 2] = expectedNormalizedTypeSize4[i * 4 + 2] =
796             Normalize10<GLshort>(unpackedInput[i][2]);
797 
798         // when the type size is 3, alpha will be 1.0f by GLES driver
799         expectedNormalizedTypeSize4[i * 4 + 3] = Normalize2<GLshort>(unpackedInput[i][3]);
800     }
801 
802     TestData data4(GL_INT_10_10_10_2_OES, GL_TRUE, Source::IMMEDIATE, packedInput.data(),
803                    expectedNormalizedTypeSize4.data());
804     TestData bufferedData4(GL_INT_10_10_10_2_OES, GL_TRUE, Source::BUFFER, packedInput.data(),
805                            expectedNormalizedTypeSize4.data());
806     TestData data3(GL_INT_10_10_10_2_OES, GL_TRUE, Source::IMMEDIATE, packedInput.data(),
807                    expectedNormalizedTypeSize3.data());
808     TestData bufferedData3(GL_INT_10_10_10_2_OES, GL_TRUE, Source::BUFFER, packedInput.data(),
809                            expectedNormalizedTypeSize3.data());
810 
811     std::array<std::pair<const TestData &, GLint>, 4> dataSet = {
812         {{data4, 4}, {bufferedData4, 4}, {data3, 3}, {bufferedData3, 3}}};
813 
814     for (auto data : dataSet)
815     {
816         setupTest(data.first, data.second);
817         drawQuad(mProgram, "position", 0.5f);
818         glDisableVertexAttribArray(mTestAttrib);
819         glDisableVertexAttribArray(mExpectedAttrib);
820         checkPixels();
821     }
822 }
823 
824 // Verify unsigned unnormalized INT_10_10_10_2 vertex type
TEST_P(VertexAttributeTest,UnsignedPacked1010102ExtensionUnnormalized)825 TEST_P(VertexAttributeTest, UnsignedPacked1010102ExtensionUnnormalized)
826 {
827     std::string extensionList(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)));
828     ANGLE_SKIP_TEST_IF((extensionList.find("OES_vertex_type_10_10_10_2") == std::string::npos));
829 
830     // RGB channels are 10-bits, alpha is 2-bits
831     std::array<std::array<GLushort, 4>, kVertexCount / 4> unpackedInput = {{{0, 1, 2, 0},
832                                                                             {511, 512, 513, 1},
833                                                                             {1023, 1022, 1021, 3},
834                                                                             {513, 512, 511, 2},
835                                                                             {2, 1, 0, 3},
836                                                                             {1023, 1022, 1022, 0}}};
837 
838     std::array<GLuint, kVertexCount> packedInput;
839     std::array<GLfloat, kVertexCount> expectedTypeSize3;
840     std::array<GLfloat, kVertexCount> expectedTypeSize4;
841 
842     for (size_t i = 0; i < kVertexCount / 4; i++)
843     {
844         packedInput[i] = Pack1010102<GLuint, GLushort>(unpackedInput[i]);
845 
846         expectedTypeSize3[i * 3 + 0] = expectedTypeSize4[i * 4 + 0] = unpackedInput[i][0];
847         expectedTypeSize3[i * 3 + 1] = expectedTypeSize4[i * 4 + 1] = unpackedInput[i][1];
848         expectedTypeSize3[i * 3 + 2] = expectedTypeSize4[i * 4 + 2] = unpackedInput[i][2];
849 
850         // when the type size is 3, alpha will be 1.0f by GLES driver
851         expectedTypeSize4[i * 4 + 3] = unpackedInput[i][3];
852     }
853 
854     TestData data4(GL_UNSIGNED_INT_10_10_10_2_OES, GL_FALSE, Source::IMMEDIATE, packedInput.data(),
855                    expectedTypeSize4.data());
856     TestData bufferedData4(GL_UNSIGNED_INT_10_10_10_2_OES, GL_FALSE, Source::BUFFER,
857                            packedInput.data(), expectedTypeSize4.data());
858     TestData data3(GL_UNSIGNED_INT_10_10_10_2_OES, GL_FALSE, Source::BUFFER, packedInput.data(),
859                    expectedTypeSize3.data());
860     TestData bufferedData3(GL_UNSIGNED_INT_10_10_10_2_OES, GL_FALSE, Source::BUFFER,
861                            packedInput.data(), expectedTypeSize3.data());
862 
863     std::array<std::pair<const TestData &, GLint>, 4> dataSet = {
864         {{data4, 4}, {bufferedData4, 4}, {data3, 3}, {bufferedData3, 3}}};
865 
866     for (auto data : dataSet)
867     {
868         setupTest(data.first, data.second);
869         drawQuad(mProgram, "position", 0.5f);
870         glDisableVertexAttribArray(mTestAttrib);
871         glDisableVertexAttribArray(mExpectedAttrib);
872         checkPixels();
873     }
874 }
875 
876 // Verify unsigned normalized INT_10_10_10_2 vertex type
TEST_P(VertexAttributeTest,UnsignedPacked1010102ExtensionNormalized)877 TEST_P(VertexAttributeTest, UnsignedPacked1010102ExtensionNormalized)
878 {
879     std::string extensionList(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)));
880     ANGLE_SKIP_TEST_IF((extensionList.find("OES_vertex_type_10_10_10_2") == std::string::npos));
881 
882     // RGB channels are 10-bits, alpha is 2-bits
883     std::array<std::array<GLushort, 4>, kVertexCount / 4> unpackedInput = {{{0, 1, 2, 0},
884                                                                             {511, 512, 513, 1},
885                                                                             {1023, 1022, 1021, 3},
886                                                                             {513, 512, 511, 2},
887                                                                             {2, 1, 0, 3},
888                                                                             {1023, 1022, 1022, 0}}};
889 
890     std::array<GLuint, kVertexCount> packedInput;
891     std::array<GLfloat, kVertexCount> expectedTypeSize4;
892     std::array<GLfloat, kVertexCount> expectedTypeSize3;
893 
894     for (size_t i = 0; i < kVertexCount / 4; i++)
895     {
896         packedInput[i] = Pack1010102<GLuint, GLushort>(unpackedInput[i]);
897 
898         expectedTypeSize3[i * 3 + 0] = expectedTypeSize4[i * 4 + 0] =
899             Normalize10<GLushort>(unpackedInput[i][0]);
900         expectedTypeSize3[i * 3 + 1] = expectedTypeSize4[i * 4 + 1] =
901             Normalize10<GLushort>(unpackedInput[i][1]);
902         expectedTypeSize3[i * 3 + 2] = expectedTypeSize4[i * 4 + 2] =
903             Normalize10<GLushort>(unpackedInput[i][2]);
904 
905         // when the type size is 3, alpha will be 1.0f by GLES driver
906         expectedTypeSize4[i * 4 + 3] = Normalize2<GLushort>(unpackedInput[i][3]);
907     }
908 
909     TestData data4(GL_UNSIGNED_INT_10_10_10_2_OES, GL_TRUE, Source::IMMEDIATE, packedInput.data(),
910                    expectedTypeSize4.data());
911     TestData bufferedData4(GL_UNSIGNED_INT_10_10_10_2_OES, GL_TRUE, Source::BUFFER,
912                            packedInput.data(), expectedTypeSize4.data());
913     TestData data3(GL_UNSIGNED_INT_10_10_10_2_OES, GL_TRUE, Source::IMMEDIATE, packedInput.data(),
914                    expectedTypeSize3.data());
915     TestData bufferedData3(GL_UNSIGNED_INT_10_10_10_2_OES, GL_TRUE, Source::BUFFER,
916                            packedInput.data(), expectedTypeSize3.data());
917 
918     std::array<std::pair<const TestData &, GLint>, 4> dataSet = {
919         {{data4, 4}, {bufferedData4, 4}, {data3, 3}, {bufferedData3, 3}}};
920 
921     for (auto data : dataSet)
922     {
923         setupTest(data.first, data.second);
924         drawQuad(mProgram, "position", 0.5f);
925         glDisableVertexAttribArray(mTestAttrib);
926         glDisableVertexAttribArray(mExpectedAttrib);
927         checkPixels();
928     };
929 }
930 
931 // Test that mixing array and current vertex attribute values works with the same matrix input
TEST_P(VertexAttributeTest,MixedMatrixSources)932 TEST_P(VertexAttributeTest, MixedMatrixSources)
933 {
934     constexpr char kVS[] = R"(
935 attribute vec4 a_position;
936 attribute mat4 a_matrix;
937 varying vec4 v_color;
938 void main() {
939     v_color = vec4(0.5, 0.25, 0.125, 0.0625) * a_matrix;
940     gl_Position = a_position;
941 })";
942 
943     constexpr char kFS[] = R"(
944 precision mediump float;
945 varying vec4 v_color;
946 void main() {
947     gl_FragColor = v_color;
948 })";
949 
950     ANGLE_GL_PROGRAM(program, kVS, kFS);
951     glBindAttribLocation(program, 0, "a_position");
952     glBindAttribLocation(program, 1, "a_matrix");
953     glLinkProgram(program);
954     glUseProgram(program);
955     ASSERT_GL_NO_ERROR();
956 
957     GLBuffer buffer;
958     for (size_t i = 0; i < 4; ++i)
959     {
960         // Setup current attributes for all columns except one
961         for (size_t col = 0; col < 4; ++col)
962         {
963             GLfloat v[4] = {0.0, 0.0, 0.0, 0.0};
964             v[col]       = col == i ? 0.0 : 1.0;
965             glVertexAttrib4fv(1 + col, v);
966             glDisableVertexAttribArray(1 + col);
967         }
968 
969         // Setup vertex array data for the i-th column
970         GLfloat data[16]{};
971         data[0 * 4 + i] = 1.0;
972         data[1 * 4 + i] = 1.0;
973         data[2 * 4 + i] = 1.0;
974         data[3 * 4 + i] = 1.0;
975         glBindBuffer(GL_ARRAY_BUFFER, buffer);
976         glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
977         glVertexAttribPointer(1 + i, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(0));
978         glEnableVertexAttribArray(1 + i);
979         ASSERT_GL_NO_ERROR();
980 
981         glClear(GL_COLOR_BUFFER_BIT);
982         drawIndexedQuad(program, "a_position", 0.0f, 1.0f, true);
983         EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
984     }
985 }
986 
987 // Test that interleaved layout works for drawing one vertex
TEST_P(VertexAttributeTest,InterleavedOneVertex)988 TEST_P(VertexAttributeTest, InterleavedOneVertex)
989 {
990     float pointSizeRange[2] = {};
991     glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, pointSizeRange);
992     ANGLE_SKIP_TEST_IF(pointSizeRange[1] < 8);
993 
994     constexpr char kVS[] = R"(
995 attribute vec4 a_pos;
996 attribute vec4 a_col;
997 varying mediump vec4 v_col;
998 void main() {
999     gl_PointSize = 8.0;
1000     gl_Position = a_pos;
1001     v_col = a_col;
1002 })";
1003     constexpr char kFS[] = R"(
1004 varying mediump vec4 v_col;
1005 void main() {
1006     gl_FragColor = v_col;
1007 })";
1008     ANGLE_GL_PROGRAM(program, kVS, kFS);
1009     glBindAttribLocation(program, 0, "a_pos");
1010     glBindAttribLocation(program, 1, "a_col");
1011     glUseProgram(program);
1012 
1013     GLBuffer buf;
1014     glBindBuffer(GL_ARRAY_BUFFER, buf);
1015 
1016     // One vertex, magenta
1017     const GLfloat data1[8] = {
1018         0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1019     };
1020 
1021     // Two vertices, red and blue
1022     const GLfloat data2[16] = {
1023         -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1024         +0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
1025     };
1026 
1027     // One vertex, green
1028     const GLfloat data3[8] = {
1029         0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
1030     };
1031 
1032     glEnableVertexAttribArray(0);
1033     glEnableVertexAttribArray(1);
1034     glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 32, reinterpret_cast<void *>(0));
1035     glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 32, reinterpret_cast<void *>(16));
1036 
1037     // The second attribute stride is reaching beyond the buffer's length.
1038     // It must not cause any errors as there only one vertex to draw.
1039     glBufferData(GL_ARRAY_BUFFER, 32, data1, GL_STATIC_DRAW);
1040     glDrawArrays(GL_POINTS, 0, 1);
1041     ASSERT_GL_NO_ERROR();
1042     EXPECT_PIXEL_COLOR_EQ(64, 64, GLColor::magenta);
1043 
1044     // Replace data and draw two vertices to ensure that stride has been applied correctly.
1045     glBufferData(GL_ARRAY_BUFFER, 64, data2, GL_STATIC_DRAW);
1046     glDrawArrays(GL_POINTS, 0, 2);
1047     ASSERT_GL_NO_ERROR();
1048     EXPECT_PIXEL_COLOR_EQ(32, 64, GLColor::red);
1049     EXPECT_PIXEL_COLOR_EQ(96, 64, GLColor::blue);
1050 
1051     // Replace data reducing the buffer size back to one vertex
1052     glBufferData(GL_ARRAY_BUFFER, 32, data3, GL_STATIC_DRAW);
1053     glDrawArrays(GL_POINTS, 0, 1);
1054     ASSERT_GL_NO_ERROR();
1055     EXPECT_PIXEL_COLOR_EQ(64, 64, GLColor::green);
1056 }
1057 
1058 class VertexAttributeTestES3 : public VertexAttributeTest
1059 {
1060   protected:
VertexAttributeTestES3()1061     VertexAttributeTestES3() {}
1062 };
1063 
TEST_P(VertexAttributeTestES3,IntUnnormalized)1064 TEST_P(VertexAttributeTestES3, IntUnnormalized)
1065 {
1066     GLint lo                                  = std::numeric_limits<GLint>::min();
1067     GLint hi                                  = std::numeric_limits<GLint>::max();
1068     std::array<GLint, kVertexCount> inputData = {
1069         {0, 1, 2, 3, -1, -2, -3, -4, -1, hi, hi - 1, lo, lo + 1}};
1070     std::array<GLfloat, kVertexCount> expectedData;
1071     for (size_t i = 0; i < kVertexCount; i++)
1072     {
1073         expectedData[i] = static_cast<GLfloat>(inputData[i]);
1074     }
1075 
1076     TestData data(GL_INT, GL_FALSE, Source::BUFFER, inputData.data(), expectedData.data());
1077     runTest(data);
1078 }
1079 
TEST_P(VertexAttributeTestES3,IntNormalized)1080 TEST_P(VertexAttributeTestES3, IntNormalized)
1081 {
1082     GLint lo                                  = std::numeric_limits<GLint>::min();
1083     GLint hi                                  = std::numeric_limits<GLint>::max();
1084     std::array<GLint, kVertexCount> inputData = {
1085         {0, 1, 2, 3, -1, -2, -3, -4, -1, hi, hi - 1, lo, lo + 1}};
1086     std::array<GLfloat, kVertexCount> expectedData;
1087     for (size_t i = 0; i < kVertexCount; i++)
1088     {
1089         expectedData[i] = Normalize(inputData[i]);
1090     }
1091 
1092     TestData data(GL_INT, GL_TRUE, Source::BUFFER, inputData.data(), expectedData.data());
1093     runTest(data);
1094 }
1095 
1096 // Same as IntUnnormalized but with glClear() before running the test to force
1097 // starting a render pass. This to verify that buffer format conversion within
1098 // an active render pass works as expected in Metal back-end.
TEST_P(VertexAttributeTestES3,IntUnnormalizedWithClear)1099 TEST_P(VertexAttributeTestES3, IntUnnormalizedWithClear)
1100 {
1101     GLint lo                                  = std::numeric_limits<GLint>::min();
1102     GLint hi                                  = std::numeric_limits<GLint>::max();
1103     std::array<GLint, kVertexCount> inputData = {
1104         {0, 1, 2, 3, -1, -2, -3, -4, -1, hi, hi - 1, lo, lo + 1}};
1105     std::array<GLfloat, kVertexCount> expectedData;
1106     for (size_t i = 0; i < kVertexCount; i++)
1107     {
1108         expectedData[i] = static_cast<GLfloat>(inputData[i]);
1109     }
1110 
1111     TestData data(GL_INT, GL_FALSE, Source::BUFFER, inputData.data(), expectedData.data());
1112     data.clearBeforeDraw = true;
1113 
1114     runTest(data);
1115 }
1116 
1117 // Same as IntNormalized but with glClear() before running the test to force
1118 // starting a render pass. This to verify that buffer format conversion within
1119 // an active render pass works as expected in Metal back-end.
TEST_P(VertexAttributeTestES3,IntNormalizedWithClear)1120 TEST_P(VertexAttributeTestES3, IntNormalizedWithClear)
1121 {
1122     GLint lo                                  = std::numeric_limits<GLint>::min();
1123     GLint hi                                  = std::numeric_limits<GLint>::max();
1124     std::array<GLint, kVertexCount> inputData = {
1125         {0, 1, 2, 3, -1, -2, -3, -4, -1, hi, hi - 1, lo, lo + 1}};
1126     std::array<GLfloat, kVertexCount> expectedData;
1127     for (size_t i = 0; i < kVertexCount; i++)
1128     {
1129         expectedData[i] = Normalize(inputData[i]);
1130     }
1131 
1132     TestData data(GL_INT, GL_TRUE, Source::BUFFER, inputData.data(), expectedData.data());
1133     data.clearBeforeDraw = true;
1134 
1135     runTest(data);
1136 }
1137 
TEST_P(VertexAttributeTestES3,UnsignedIntUnnormalized)1138 TEST_P(VertexAttributeTestES3, UnsignedIntUnnormalized)
1139 {
1140     GLuint mid                                 = std::numeric_limits<GLuint>::max() >> 1;
1141     GLuint hi                                  = std::numeric_limits<GLuint>::max();
1142     std::array<GLuint, kVertexCount> inputData = {
1143         {0, 1, 2, 3, 254, 255, 256, mid - 1, mid, mid + 1, hi - 2, hi - 1, hi}};
1144     std::array<GLfloat, kVertexCount> expectedData;
1145     for (size_t i = 0; i < kVertexCount; i++)
1146     {
1147         expectedData[i] = static_cast<GLfloat>(inputData[i]);
1148     }
1149 
1150     TestData data(GL_UNSIGNED_INT, GL_FALSE, Source::BUFFER, inputData.data(), expectedData.data());
1151     runTest(data);
1152 }
1153 
TEST_P(VertexAttributeTestES3,UnsignedIntNormalized)1154 TEST_P(VertexAttributeTestES3, UnsignedIntNormalized)
1155 {
1156     GLuint mid                                 = std::numeric_limits<GLuint>::max() >> 1;
1157     GLuint hi                                  = std::numeric_limits<GLuint>::max();
1158     std::array<GLuint, kVertexCount> inputData = {
1159         {0, 1, 2, 3, 254, 255, 256, mid - 1, mid, mid + 1, hi - 2, hi - 1, hi}};
1160     std::array<GLfloat, kVertexCount> expectedData;
1161     for (size_t i = 0; i < kVertexCount; i++)
1162     {
1163         expectedData[i] = Normalize(inputData[i]);
1164     }
1165 
1166     TestData data(GL_UNSIGNED_INT, GL_TRUE, Source::BUFFER, inputData.data(), expectedData.data());
1167     runTest(data);
1168 }
1169 
1170 // Same as UnsignedIntNormalized but with glClear() before running the test to force
1171 // starting a render pass. This to verify that buffer format conversion within
1172 // an active render pass works as expected in Metal back-end.
TEST_P(VertexAttributeTestES3,UnsignedIntNormalizedWithClear)1173 TEST_P(VertexAttributeTestES3, UnsignedIntNormalizedWithClear)
1174 {
1175     GLuint mid                                 = std::numeric_limits<GLuint>::max() >> 1;
1176     GLuint hi                                  = std::numeric_limits<GLuint>::max();
1177     std::array<GLuint, kVertexCount> inputData = {
1178         {0, 1, 2, 3, 254, 255, 256, mid - 1, mid, mid + 1, hi - 2, hi - 1, hi}};
1179     std::array<GLfloat, kVertexCount> expectedData;
1180     for (size_t i = 0; i < kVertexCount; i++)
1181     {
1182         expectedData[i] = Normalize(inputData[i]);
1183     }
1184 
1185     TestData data(GL_UNSIGNED_INT, GL_TRUE, Source::BUFFER, inputData.data(), expectedData.data());
1186     data.clearBeforeDraw = true;
1187     runTest(data);
1188 }
1189 
SetupColorsForUnitQuad(GLint location,const GLColor32F & color,GLenum usage,GLBuffer * vbo)1190 void SetupColorsForUnitQuad(GLint location, const GLColor32F &color, GLenum usage, GLBuffer *vbo)
1191 {
1192     glBindBuffer(GL_ARRAY_BUFFER, *vbo);
1193     std::vector<GLColor32F> vertices(6, color);
1194     glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLColor32F), vertices.data(), usage);
1195     glEnableVertexAttribArray(location);
1196     glVertexAttribPointer(location, 4, GL_FLOAT, GL_FALSE, 0, 0);
1197 }
1198 
1199 // Tests that rendering works as expected with VAOs.
TEST_P(VertexAttributeTestES3,VertexArrayObjectRendering)1200 TEST_P(VertexAttributeTestES3, VertexArrayObjectRendering)
1201 {
1202     constexpr char kVertexShader[] =
1203         "attribute vec4 a_position;\n"
1204         "attribute vec4 a_color;\n"
1205         "varying vec4 v_color;\n"
1206         "void main()\n"
1207         "{\n"
1208         "   gl_Position = a_position;\n"
1209         "   v_color = a_color;\n"
1210         "}";
1211 
1212     constexpr char kFragmentShader[] =
1213         "precision mediump float;\n"
1214         "varying vec4 v_color;\n"
1215         "void main()\n"
1216         "{\n"
1217         "    gl_FragColor = v_color;\n"
1218         "}";
1219 
1220     ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
1221 
1222     GLint positionLoc = glGetAttribLocation(program, "a_position");
1223     ASSERT_NE(-1, positionLoc);
1224     GLint colorLoc = glGetAttribLocation(program, "a_color");
1225     ASSERT_NE(-1, colorLoc);
1226 
1227     GLVertexArray vaos[2];
1228     GLBuffer positionBuffer;
1229     GLBuffer colorBuffers[2];
1230 
1231     const auto &quadVertices = GetQuadVertices();
1232 
1233     glBindVertexArray(vaos[0]);
1234     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
1235     glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
1236                  GL_STATIC_DRAW);
1237     glEnableVertexAttribArray(positionLoc);
1238     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
1239     SetupColorsForUnitQuad(colorLoc, kFloatRed, GL_STREAM_DRAW, &colorBuffers[0]);
1240 
1241     glBindVertexArray(vaos[1]);
1242     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
1243     glEnableVertexAttribArray(positionLoc);
1244     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
1245     SetupColorsForUnitQuad(colorLoc, kFloatGreen, GL_STATIC_DRAW, &colorBuffers[1]);
1246 
1247     glUseProgram(program);
1248     ASSERT_GL_NO_ERROR();
1249 
1250     for (int ii = 0; ii < 2; ++ii)
1251     {
1252         glBindVertexArray(vaos[0]);
1253         glDrawArrays(GL_TRIANGLES, 0, 6);
1254         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1255 
1256         glBindVertexArray(vaos[1]);
1257         glDrawArrays(GL_TRIANGLES, 0, 6);
1258         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1259     }
1260 
1261     ASSERT_GL_NO_ERROR();
1262 }
1263 
1264 // Validate that we can support GL_MAX_ATTRIBS attribs
TEST_P(VertexAttributeTest,MaxAttribs)1265 TEST_P(VertexAttributeTest, MaxAttribs)
1266 {
1267     // TODO(jmadill): Figure out why we get this error on AMD/OpenGL.
1268     ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
1269 
1270     GLint maxAttribs;
1271     glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttribs);
1272     ASSERT_GL_NO_ERROR();
1273 
1274     // Reserve one attrib for position
1275     GLint drawAttribs = maxAttribs - 1;
1276 
1277     GLuint program = compileMultiAttribProgram(drawAttribs);
1278     ASSERT_NE(0u, program);
1279 
1280     setupMultiAttribs(program, drawAttribs, 0.5f / static_cast<float>(drawAttribs));
1281     drawQuad(program, "position", 0.5f);
1282 
1283     EXPECT_GL_NO_ERROR();
1284     EXPECT_PIXEL_NEAR(0, 0, 128, 0, 0, 255, 1);
1285 }
1286 
1287 // Validate that we cannot support GL_MAX_ATTRIBS+1 attribs
TEST_P(VertexAttributeTest,MaxAttribsPlusOne)1288 TEST_P(VertexAttributeTest, MaxAttribsPlusOne)
1289 {
1290     // TODO(jmadill): Figure out why we get this error on AMD/ES2/OpenGL
1291     ANGLE_SKIP_TEST_IF(IsAMD() && GetParam() == ES2_OPENGL());
1292 
1293     GLint maxAttribs;
1294     glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttribs);
1295     ASSERT_GL_NO_ERROR();
1296 
1297     // Exceed attrib count by one (counting position)
1298     GLint drawAttribs = maxAttribs;
1299 
1300     GLuint program = compileMultiAttribProgram(drawAttribs);
1301     ASSERT_EQ(0u, program);
1302 }
1303 
1304 // Simple test for when we use glBindAttribLocation
TEST_P(VertexAttributeTest,SimpleBindAttribLocation)1305 TEST_P(VertexAttributeTest, SimpleBindAttribLocation)
1306 {
1307     // Re-use the multi-attrib program, binding attribute 0
1308     GLuint program = compileMultiAttribProgram(1);
1309     glBindAttribLocation(program, 2, "position");
1310     glBindAttribLocation(program, 3, "a0");
1311     glLinkProgram(program);
1312 
1313     // Setup and draw the quad
1314     setupMultiAttribs(program, 1, 0.5f);
1315     drawQuad(program, "position", 0.5f);
1316     EXPECT_GL_NO_ERROR();
1317     EXPECT_PIXEL_NEAR(0, 0, 128, 0, 0, 255, 1);
1318 }
1319 
1320 class VertexAttributeOORTest : public VertexAttributeTest
1321 {
1322   public:
VertexAttributeOORTest()1323     VertexAttributeOORTest()
1324     {
1325         setWebGLCompatibilityEnabled(true);
1326         setRobustAccess(false);
1327     }
1328 };
1329 
1330 class RobustVertexAttributeTest : public VertexAttributeTest
1331 {
1332   public:
RobustVertexAttributeTest()1333     RobustVertexAttributeTest()
1334     {
1335         // mac GL and metal do not support robustness.
1336         if (!IsMac() && !IsIOS())
1337         {
1338             setRobustAccess(true);
1339         }
1340     }
1341 };
1342 
1343 // Verify that drawing with a large out-of-range offset generates INVALID_OPERATION.
1344 // Requires WebGL compatibility with robust access behaviour disabled.
TEST_P(VertexAttributeOORTest,ANGLEDrawArraysBufferTooSmall)1345 TEST_P(VertexAttributeOORTest, ANGLEDrawArraysBufferTooSmall)
1346 {
1347     // Test skipped due to supporting GL_KHR_robust_buffer_access_behavior
1348     ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_KHR_robust_buffer_access_behavior"));
1349 
1350     std::array<GLfloat, kVertexCount> inputData;
1351     std::array<GLfloat, kVertexCount> expectedData;
1352     InitTestData(inputData, expectedData);
1353 
1354     TestData data(GL_FLOAT, GL_FALSE, Source::BUFFER, inputData.data(), expectedData.data());
1355     data.bufferOffset = kVertexCount * TypeStride(GL_FLOAT);
1356 
1357     setupTest(data, 1);
1358     drawQuad(mProgram, "position", 0.5f);
1359     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1360 }
1361 
1362 // Verify that index draw with an out-of-range offset generates INVALID_OPERATION.
1363 // Requires WebGL compatibility with robust access behaviour disabled.
TEST_P(VertexAttributeOORTest,ANGLEDrawElementsBufferTooSmall)1364 TEST_P(VertexAttributeOORTest, ANGLEDrawElementsBufferTooSmall)
1365 {
1366     // Test skipped due to supporting GL_KHR_robust_buffer_access_behavior
1367     ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_KHR_robust_buffer_access_behavior"));
1368 
1369     std::array<GLfloat, kVertexCount> inputData;
1370     std::array<GLfloat, kVertexCount> expectedData;
1371     InitTestData(inputData, expectedData);
1372 
1373     TestData data(GL_FLOAT, GL_FALSE, Source::BUFFER, inputData.data(), expectedData.data());
1374     data.bufferOffset = (kVertexCount - 3) * TypeStride(GL_FLOAT);
1375 
1376     setupTest(data, 1);
1377     drawIndexedQuad(mProgram, "position", 0.5f, 1.0f, true);
1378     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1379 }
1380 
1381 // Verify that DrawArarys with an out-of-range offset generates INVALID_OPERATION.
1382 // Requires WebGL compatibility with robust access behaviour disabled.
TEST_P(VertexAttributeOORTest,ANGLEDrawArraysOutOfBoundsCases)1383 TEST_P(VertexAttributeOORTest, ANGLEDrawArraysOutOfBoundsCases)
1384 {
1385     // Test skipped due to supporting GL_KHR_robust_buffer_access_behavior
1386     ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_KHR_robust_buffer_access_behavior"));
1387 
1388     initBasicProgram();
1389 
1390     GLfloat singleFloat = 1.0f;
1391     GLsizei dataSize    = TypeStride(GL_FLOAT);
1392 
1393     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1394     glBufferData(GL_ARRAY_BUFFER, dataSize, &singleFloat, GL_STATIC_DRAW);
1395     glVertexAttribPointer(mTestAttrib, 2, GL_FLOAT, GL_FALSE, 8, 0);
1396     glEnableVertexAttribArray(mTestAttrib);
1397     glBindBuffer(GL_ARRAY_BUFFER, 0);
1398 
1399     drawIndexedQuad(mProgram, "position", 0.5f, 1.0f, true);
1400     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1401 }
1402 
1403 // Test that enabling a buffer in an unused attribute doesn't crash.  There should be an active
1404 // attribute after that.
TEST_P(RobustVertexAttributeTest,BoundButUnusedBuffer)1405 TEST_P(RobustVertexAttributeTest, BoundButUnusedBuffer)
1406 {
1407     constexpr char kVS[] = R"(attribute vec2 offset;
1408 void main()
1409 {
1410     gl_Position = vec4(offset.xy, 0, 1);
1411     gl_PointSize = 1.0;
1412 })";
1413 
1414     constexpr char kFS[] = R"(precision mediump float;
1415 void main()
1416 {
1417     gl_FragColor = vec4(1.0, 0, 0, 1.0);
1418 })";
1419 
1420     const GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
1421     const GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
1422 
1423     GLuint program = glCreateProgram();
1424     glBindAttribLocation(program, 1, "offset");
1425     glAttachShader(program, vs);
1426     glAttachShader(program, fs);
1427     glLinkProgram(program);
1428 
1429     GLBuffer buffer;
1430     glBindBuffer(GL_ARRAY_BUFFER, buffer);
1431     glBufferData(GL_ARRAY_BUFFER, 100, nullptr, GL_STATIC_DRAW);
1432 
1433     // Enable an unused attribute that is within the range of active attributes (not beyond it)
1434     glEnableVertexAttribArray(0);
1435     glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, 0);
1436 
1437     glUseProgram(program);
1438     glDrawArrays(GL_TRIANGLES, 0, 6);
1439 
1440     // Destroy the buffer.  Regression test for a tracking bug where the buffer was used by
1441     // SwiftShader (even though location 1 is inactive), but not marked as used by ANGLE.
1442     buffer.reset();
1443 }
1444 
1445 // Verify that using a different start vertex doesn't mess up the draw.
TEST_P(VertexAttributeTest,DrawArraysWithBufferOffset)1446 TEST_P(VertexAttributeTest, DrawArraysWithBufferOffset)
1447 {
1448     initBasicProgram();
1449     glUseProgram(mProgram);
1450 
1451     std::array<GLfloat, kVertexCount> inputData;
1452     std::array<GLfloat, kVertexCount> expectedData;
1453     InitTestData(inputData, expectedData);
1454 
1455     GLBuffer quadBuffer;
1456     InitQuadPlusOneVertexBuffer(&quadBuffer);
1457 
1458     GLint positionLocation = glGetAttribLocation(mProgram, "position");
1459     ASSERT_NE(-1, positionLocation);
1460     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1461     glEnableVertexAttribArray(positionLocation);
1462 
1463     GLsizei dataSize = kVertexCount * TypeStride(GL_FLOAT);
1464     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1465     glBufferData(GL_ARRAY_BUFFER, dataSize + TypeStride(GL_FLOAT), nullptr, GL_STATIC_DRAW);
1466     glBufferSubData(GL_ARRAY_BUFFER, 0, dataSize, inputData.data());
1467     glVertexAttribPointer(mTestAttrib, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1468     glEnableVertexAttribArray(mTestAttrib);
1469 
1470     glBindBuffer(GL_ARRAY_BUFFER, 0);
1471     glVertexAttribPointer(mExpectedAttrib, 1, GL_FLOAT, GL_FALSE, 0, expectedData.data());
1472     glEnableVertexAttribArray(mExpectedAttrib);
1473 
1474     // Vertex draw with no start vertex offset (second argument is zero).
1475     glDrawArrays(GL_TRIANGLES, 0, 6);
1476     checkPixels();
1477 
1478     // Draw offset by one vertex.
1479     glDrawArrays(GL_TRIANGLES, 1, 6);
1480     checkPixels();
1481 
1482     EXPECT_GL_NO_ERROR();
1483 }
1484 
1485 // Verify that using an unaligned offset doesn't mess up the draw.
TEST_P(VertexAttributeTest,DrawArraysWithUnalignedBufferOffset)1486 TEST_P(VertexAttributeTest, DrawArraysWithUnalignedBufferOffset)
1487 {
1488     initBasicProgram();
1489     glUseProgram(mProgram);
1490 
1491     std::array<GLfloat, kVertexCount> inputData;
1492     std::array<GLfloat, kVertexCount> expectedData;
1493     InitTestData(inputData, expectedData);
1494 
1495     GLBuffer quadBuffer;
1496     InitQuadPlusOneVertexBuffer(&quadBuffer);
1497 
1498     GLint positionLocation = glGetAttribLocation(mProgram, "position");
1499     ASSERT_NE(-1, positionLocation);
1500     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1501     glEnableVertexAttribArray(positionLocation);
1502 
1503     // Unaligned buffer offset (3)
1504     GLsizei dataSize = kVertexCount * TypeStride(GL_FLOAT) + 3;
1505     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1506     glBufferData(GL_ARRAY_BUFFER, dataSize, nullptr, GL_STATIC_DRAW);
1507     glBufferSubData(GL_ARRAY_BUFFER, 3, dataSize - 3, inputData.data());
1508     glVertexAttribPointer(mTestAttrib, 1, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(3));
1509     glEnableVertexAttribArray(mTestAttrib);
1510 
1511     glBindBuffer(GL_ARRAY_BUFFER, 0);
1512     glVertexAttribPointer(mExpectedAttrib, 1, GL_FLOAT, GL_FALSE, 0, expectedData.data());
1513     glEnableVertexAttribArray(mExpectedAttrib);
1514 
1515     // Vertex draw with no start vertex offset (second argument is zero).
1516     glDrawArrays(GL_TRIANGLES, 0, 6);
1517     checkPixels();
1518 
1519     // Draw offset by one vertex.
1520     glDrawArrays(GL_TRIANGLES, 1, 6);
1521     checkPixels();
1522 
1523     EXPECT_GL_NO_ERROR();
1524 }
1525 
1526 // Verify that using an unaligned offset & GL_SHORT vertex attribute doesn't mess up the draw.
1527 // In Metal backend, GL_SHORTx3 is coverted to GL_SHORTx4 if offset is unaligned.
TEST_P(VertexAttributeTest,DrawArraysWithUnalignedShortBufferOffset)1528 TEST_P(VertexAttributeTest, DrawArraysWithUnalignedShortBufferOffset)
1529 {
1530     initBasicProgram();
1531     glUseProgram(mProgram);
1532 
1533     // input data is GL_SHORTx3 (6 bytes) but stride=8
1534     std::array<GLshort, 4 * kVertexCount> inputData;
1535     std::array<GLfloat, 3 * kVertexCount> expectedData;
1536     for (size_t i = 0; i < kVertexCount; ++i)
1537     {
1538         inputData[4 * i]     = 3 * i;
1539         inputData[4 * i + 1] = 3 * i + 1;
1540         inputData[4 * i + 2] = 3 * i + 2;
1541 
1542         expectedData[3 * i]     = 3 * i;
1543         expectedData[3 * i + 1] = 3 * i + 1;
1544         expectedData[3 * i + 2] = 3 * i + 2;
1545     }
1546 
1547     GLBuffer quadBuffer;
1548     InitQuadPlusOneVertexBuffer(&quadBuffer);
1549 
1550     GLint positionLocation = glGetAttribLocation(mProgram, "position");
1551     ASSERT_NE(-1, positionLocation);
1552     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1553     glEnableVertexAttribArray(positionLocation);
1554 
1555     // Unaligned buffer offset (8)
1556     GLsizei dataSize = 3 * kVertexCount * TypeStride(GL_SHORT) + 8;
1557     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1558     glBufferData(GL_ARRAY_BUFFER, dataSize, nullptr, GL_STATIC_DRAW);
1559     glBufferSubData(GL_ARRAY_BUFFER, 8, dataSize - 8, inputData.data());
1560     glVertexAttribPointer(mTestAttrib, 3, GL_SHORT, GL_FALSE, /* stride */ 8,
1561                           reinterpret_cast<void *>(8));
1562     glEnableVertexAttribArray(mTestAttrib);
1563 
1564     glBindBuffer(GL_ARRAY_BUFFER, 0);
1565     glVertexAttribPointer(mExpectedAttrib, 3, GL_FLOAT, GL_FALSE, 0, expectedData.data());
1566     glEnableVertexAttribArray(mExpectedAttrib);
1567 
1568     // Vertex draw with no start vertex offset (second argument is zero).
1569     glDrawArrays(GL_TRIANGLES, 0, 6);
1570     checkPixels();
1571 
1572     // Draw offset by one vertex.
1573     glDrawArrays(GL_TRIANGLES, 1, 6);
1574     checkPixels();
1575 
1576     EXPECT_GL_NO_ERROR();
1577 }
1578 
1579 // Verify that using a GL_FLOATx2 attribute with offset not divisible by 8 works.
TEST_P(VertexAttributeTest,DrawArraysWith2FloatAtOffsetNotDivisbleBy8)1580 TEST_P(VertexAttributeTest, DrawArraysWith2FloatAtOffsetNotDivisbleBy8)
1581 {
1582     initBasicProgram();
1583     glUseProgram(mProgram);
1584 
1585     // input data is GL_FLOATx2 (8 bytes) and stride=36
1586     std::array<GLubyte, 36 * kVertexCount> inputData;
1587     std::array<GLfloat, 2 * kVertexCount> expectedData;
1588     for (size_t i = 0; i < kVertexCount; ++i)
1589     {
1590         expectedData[2 * i]     = 2 * i;
1591         expectedData[2 * i + 1] = 2 * i + 1;
1592 
1593         GLubyte *input = inputData.data() + 36 * i;
1594         memcpy(input, &expectedData[2 * i], sizeof(float));
1595         memcpy(input + sizeof(float), &expectedData[2 * i + 1], sizeof(float));
1596     }
1597 
1598     GLBuffer quadBuffer;
1599     InitQuadPlusOneVertexBuffer(&quadBuffer);
1600 
1601     GLint positionLocation = glGetAttribLocation(mProgram, "position");
1602     ASSERT_NE(-1, positionLocation);
1603     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1604     glEnableVertexAttribArray(positionLocation);
1605 
1606     // offset is not float2 aligned (28)
1607     GLsizei dataSize = 36 * kVertexCount + 28;
1608     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1609     glBufferData(GL_ARRAY_BUFFER, dataSize, nullptr, GL_STATIC_DRAW);
1610     glBufferSubData(GL_ARRAY_BUFFER, 28, dataSize - 28, inputData.data());
1611     glVertexAttribPointer(mTestAttrib, 2, GL_FLOAT, GL_FALSE, /* stride */ 36,
1612                           reinterpret_cast<void *>(28));
1613     glEnableVertexAttribArray(mTestAttrib);
1614 
1615     glBindBuffer(GL_ARRAY_BUFFER, 0);
1616     glVertexAttribPointer(mExpectedAttrib, 2, GL_FLOAT, GL_FALSE, 0, expectedData.data());
1617     glEnableVertexAttribArray(mExpectedAttrib);
1618 
1619     // Vertex draw with no start vertex offset (second argument is zero).
1620     glDrawArrays(GL_TRIANGLES, 0, 6);
1621     checkPixels();
1622 
1623     // Draw offset by one vertex.
1624     glDrawArrays(GL_TRIANGLES, 1, 6);
1625     checkPixels();
1626 
1627     EXPECT_GL_NO_ERROR();
1628 }
1629 
1630 // Verify that using offset=1 for GL_BYTE vertex attribute doesn't mess up the draw.
1631 // Depending on backend, offset=1 for GL_BYTE could be natively supported or not.
1632 // In the latter case, a vertex data conversion will have to be performed.
TEST_P(VertexAttributeTest,DrawArraysWithByteAtOffset1)1633 TEST_P(VertexAttributeTest, DrawArraysWithByteAtOffset1)
1634 {
1635     initBasicProgram();
1636     glUseProgram(mProgram);
1637 
1638     // input data is GL_BYTEx3 (3 bytes) but stride=4
1639     std::array<GLbyte, 4 * kVertexCount> inputData;
1640     std::array<GLfloat, 3 * kVertexCount> expectedData;
1641     for (size_t i = 0; i < kVertexCount; ++i)
1642     {
1643         inputData[4 * i]     = 3 * i;
1644         inputData[4 * i + 1] = 3 * i + 1;
1645         inputData[4 * i + 2] = 3 * i + 2;
1646 
1647         expectedData[3 * i]     = 3 * i;
1648         expectedData[3 * i + 1] = 3 * i + 1;
1649         expectedData[3 * i + 2] = 3 * i + 2;
1650     }
1651 
1652     GLBuffer quadBuffer;
1653     InitQuadPlusOneVertexBuffer(&quadBuffer);
1654 
1655     GLint positionLocation = glGetAttribLocation(mProgram, "position");
1656     ASSERT_NE(-1, positionLocation);
1657     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1658     glEnableVertexAttribArray(positionLocation);
1659 
1660     // Buffer offset (1)
1661     GLsizei dataSize = 4 * kVertexCount + 1;
1662     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1663     glBufferData(GL_ARRAY_BUFFER, dataSize, nullptr, GL_STATIC_DRAW);
1664     glBufferSubData(GL_ARRAY_BUFFER, 1, dataSize - 1, inputData.data());
1665     glVertexAttribPointer(mTestAttrib, 3, GL_BYTE, GL_FALSE, /* stride */ 4,
1666                           reinterpret_cast<void *>(1));
1667     glEnableVertexAttribArray(mTestAttrib);
1668 
1669     glBindBuffer(GL_ARRAY_BUFFER, 0);
1670     glVertexAttribPointer(mExpectedAttrib, 3, GL_FLOAT, GL_FALSE, 0, expectedData.data());
1671     glEnableVertexAttribArray(mExpectedAttrib);
1672 
1673     // Vertex draw with no start vertex offset (second argument is zero).
1674     glDrawArrays(GL_TRIANGLES, 0, 6);
1675     checkPixels();
1676 
1677     // Draw offset by one vertex.
1678     glDrawArrays(GL_TRIANGLES, 1, 6);
1679     checkPixels();
1680 
1681     EXPECT_GL_NO_ERROR();
1682 }
1683 
1684 // Verify that using an aligned but non-multiples of 4 offset vertex attribute doesn't mess up the
1685 // draw.
TEST_P(VertexAttributeTest,DrawArraysWithShortBufferOffsetNotMultipleOf4)1686 TEST_P(VertexAttributeTest, DrawArraysWithShortBufferOffsetNotMultipleOf4)
1687 {
1688     // http://anglebug.com/42263937
1689     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
1690 
1691     initBasicProgram();
1692     glUseProgram(mProgram);
1693 
1694     // input data is GL_SHORTx3 (6 bytes) but stride=8
1695     std::array<GLshort, 4 * kVertexCount> inputData;
1696     std::array<GLfloat, 3 * kVertexCount> expectedData;
1697     for (size_t i = 0; i < kVertexCount; ++i)
1698     {
1699         inputData[4 * i]     = 3 * i;
1700         inputData[4 * i + 1] = 3 * i + 1;
1701         inputData[4 * i + 2] = 3 * i + 2;
1702 
1703         expectedData[3 * i]     = 3 * i;
1704         expectedData[3 * i + 1] = 3 * i + 1;
1705         expectedData[3 * i + 2] = 3 * i + 2;
1706     }
1707 
1708     GLBuffer quadBuffer;
1709     InitQuadPlusOneVertexBuffer(&quadBuffer);
1710 
1711     GLint positionLocation = glGetAttribLocation(mProgram, "position");
1712     ASSERT_NE(-1, positionLocation);
1713     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1714     glEnableVertexAttribArray(positionLocation);
1715 
1716     // Aligned but not multiples of 4 buffer offset (18)
1717     GLsizei dataSize = 4 * kVertexCount * TypeStride(GL_SHORT) + 8;
1718     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1719     glBufferData(GL_ARRAY_BUFFER, dataSize, nullptr, GL_STATIC_DRAW);
1720     glBufferSubData(GL_ARRAY_BUFFER, 18, dataSize - 18, inputData.data());
1721     glVertexAttribPointer(mTestAttrib, 3, GL_SHORT, GL_FALSE, /* stride */ 8,
1722                           reinterpret_cast<void *>(18));
1723     glEnableVertexAttribArray(mTestAttrib);
1724 
1725     glBindBuffer(GL_ARRAY_BUFFER, 0);
1726     glVertexAttribPointer(mExpectedAttrib, 3, GL_FLOAT, GL_FALSE, 0, expectedData.data());
1727     glEnableVertexAttribArray(mExpectedAttrib);
1728 
1729     // Vertex draw with no start vertex offset (second argument is zero).
1730     glDrawArrays(GL_TRIANGLES, 0, 6);
1731     checkPixels();
1732 
1733     // Draw offset by one vertex.
1734     glDrawArrays(GL_TRIANGLES, 1, 6);
1735     checkPixels();
1736 
1737     EXPECT_GL_NO_ERROR();
1738 }
1739 
1740 // Verify that using both aligned and unaligned offsets doesn't mess up the draw.
TEST_P(VertexAttributeTest,DrawArraysWithAlignedAndUnalignedBufferOffset)1741 TEST_P(VertexAttributeTest, DrawArraysWithAlignedAndUnalignedBufferOffset)
1742 {
1743     initBasicProgram();
1744     glUseProgram(mProgram);
1745 
1746     std::array<GLfloat, kVertexCount> inputData;
1747     std::array<GLfloat, kVertexCount> expectedData;
1748     InitTestData(inputData, expectedData);
1749 
1750     GLBuffer quadBuffer;
1751     InitQuadPlusOneVertexBuffer(&quadBuffer);
1752 
1753     GLint positionLocation = glGetAttribLocation(mProgram, "position");
1754     ASSERT_NE(-1, positionLocation);
1755     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1756     glEnableVertexAttribArray(positionLocation);
1757 
1758     // ----------- Aligned buffer offset (4) -------------
1759     GLsizei dataSize = kVertexCount * TypeStride(GL_FLOAT) + 4;
1760     GLBuffer alignedBufer;
1761     glBindBuffer(GL_ARRAY_BUFFER, alignedBufer);
1762     glBufferData(GL_ARRAY_BUFFER, dataSize, nullptr, GL_STATIC_DRAW);
1763     glBufferSubData(GL_ARRAY_BUFFER, 4, dataSize - 4, inputData.data());
1764     glVertexAttribPointer(mTestAttrib, 1, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(4));
1765     glEnableVertexAttribArray(mTestAttrib);
1766 
1767     glBindBuffer(GL_ARRAY_BUFFER, 0);
1768     glVertexAttribPointer(mExpectedAttrib, 1, GL_FLOAT, GL_FALSE, 0, expectedData.data());
1769     glEnableVertexAttribArray(mExpectedAttrib);
1770 
1771     // Vertex draw with no start vertex offset (second argument is zero).
1772     glDrawArrays(GL_TRIANGLES, 0, 6);
1773     checkPixels();
1774 
1775     // Draw offset by one vertex.
1776     glDrawArrays(GL_TRIANGLES, 1, 6);
1777     checkPixels();
1778 
1779     // ----------- Unaligned buffer offset (3) -------------
1780     glClear(GL_COLOR_BUFFER_BIT);
1781 
1782     dataSize = kVertexCount * TypeStride(GL_FLOAT) + 3;
1783     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1784     glBufferData(GL_ARRAY_BUFFER, dataSize, nullptr, GL_STATIC_DRAW);
1785     glBufferSubData(GL_ARRAY_BUFFER, 3, dataSize - 3, inputData.data());
1786     glVertexAttribPointer(mTestAttrib, 1, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(3));
1787     glEnableVertexAttribArray(mTestAttrib);
1788 
1789     glBindBuffer(GL_ARRAY_BUFFER, 0);
1790     glVertexAttribPointer(mExpectedAttrib, 1, GL_FLOAT, GL_FALSE, 0, expectedData.data());
1791     glEnableVertexAttribArray(mExpectedAttrib);
1792 
1793     // Vertex draw with no start vertex offset (second argument is zero).
1794     glDrawArrays(GL_TRIANGLES, 0, 6);
1795     checkPixels();
1796 
1797     // Draw offset by one vertex.
1798     glDrawArrays(GL_TRIANGLES, 1, 6);
1799     checkPixels();
1800 
1801     EXPECT_GL_NO_ERROR();
1802 }
1803 
1804 // Verify that when we pass a client memory pointer to a disabled attribute the draw is still
1805 // correct.
TEST_P(VertexAttributeTest,DrawArraysWithDisabledAttribute)1806 TEST_P(VertexAttributeTest, DrawArraysWithDisabledAttribute)
1807 {
1808     initBasicProgram();
1809 
1810     std::array<GLfloat, kVertexCount> inputData;
1811     std::array<GLfloat, kVertexCount> expectedData;
1812     InitTestData(inputData, expectedData);
1813 
1814     GLBuffer buffer;
1815     InitQuadVertexBuffer(&buffer);
1816 
1817     GLint positionLocation = glGetAttribLocation(mProgram, "position");
1818     ASSERT_NE(-1, positionLocation);
1819     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1820     glEnableVertexAttribArray(positionLocation);
1821 
1822     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1823     glBufferData(GL_ARRAY_BUFFER, sizeof(inputData), inputData.data(), GL_STATIC_DRAW);
1824     glVertexAttribPointer(mTestAttrib, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1825     glEnableVertexAttribArray(mTestAttrib);
1826 
1827     glBindBuffer(GL_ARRAY_BUFFER, 0);
1828     glVertexAttribPointer(mExpectedAttrib, 1, GL_FLOAT, GL_FALSE, 0, expectedData.data());
1829     glEnableVertexAttribArray(mExpectedAttrib);
1830 
1831     // mProgram2 adds an attribute 'disabled' on the basis of mProgram.
1832     constexpr char testVertexShaderSource2[] =
1833         "attribute mediump vec4 position;\n"
1834         "attribute mediump vec4 test;\n"
1835         "attribute mediump vec4 expected;\n"
1836         "attribute mediump vec4 disabled;\n"
1837         "varying mediump vec4 color;\n"
1838         "void main(void)\n"
1839         "{\n"
1840         "    gl_Position = position;\n"
1841         "    vec4 threshold = max(abs(expected + disabled) * 0.005, 1.0 / 64.0);\n"
1842         "    color = vec4(lessThanEqual(abs(test - expected), threshold));\n"
1843         "}\n";
1844 
1845     constexpr char testFragmentShaderSource[] =
1846         "varying mediump vec4 color;\n"
1847         "void main(void)\n"
1848         "{\n"
1849         "    gl_FragColor = color;\n"
1850         "}\n";
1851 
1852     ANGLE_GL_PROGRAM(program, testVertexShaderSource2, testFragmentShaderSource);
1853     GLuint mProgram2 = program;
1854 
1855     ASSERT_EQ(positionLocation, glGetAttribLocation(mProgram2, "position"));
1856     ASSERT_EQ(mTestAttrib, glGetAttribLocation(mProgram2, "test"));
1857     ASSERT_EQ(mExpectedAttrib, glGetAttribLocation(mProgram2, "expected"));
1858 
1859     // Pass a client memory pointer to disabledAttribute and disable it.
1860     GLint disabledAttribute = glGetAttribLocation(mProgram2, "disabled");
1861     ASSERT_EQ(-1, glGetAttribLocation(mProgram, "disabled"));
1862     glVertexAttribPointer(disabledAttribute, 1, GL_FLOAT, GL_FALSE, 0, expectedData.data());
1863     glDisableVertexAttribArray(disabledAttribute);
1864 
1865     glUseProgram(mProgram);
1866     glDrawArrays(GL_TRIANGLES, 0, 6);
1867     checkPixels();
1868 
1869     // Now enable disabledAttribute which should be used in mProgram2.
1870     glEnableVertexAttribArray(disabledAttribute);
1871     glUseProgram(mProgram2);
1872     glDrawArrays(GL_TRIANGLES, 0, 6);
1873     checkPixels();
1874 
1875     EXPECT_GL_NO_ERROR();
1876 }
1877 
1878 // Test based on WebGL Test attribs/gl-disabled-vertex-attrib.html
TEST_P(VertexAttributeTest,DisabledAttribArrays)1879 TEST_P(VertexAttributeTest, DisabledAttribArrays)
1880 {
1881     // Known failure on Retina MBP: http://crbug.com/635081
1882     ANGLE_SKIP_TEST_IF(IsMac() && IsNVIDIA());
1883 
1884     constexpr char kVS[] =
1885         "attribute vec4 a_position;\n"
1886         "attribute vec4 a_color;\n"
1887         "varying vec4 v_color;\n"
1888         "bool isCorrectColor(vec4 v) {\n"
1889         "    return v.x == 0.0 && v.y == 0.0 && v.z == 0.0 && v.w == 1.0;\n"
1890         "}"
1891         "void main() {\n"
1892         "    gl_Position = a_position;\n"
1893         "    v_color = isCorrectColor(a_color) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
1894         "}";
1895 
1896     constexpr char kFS[] =
1897         "varying mediump vec4 v_color;\n"
1898         "void main() {\n"
1899         "    gl_FragColor = v_color;\n"
1900         "}";
1901 
1902     GLint maxVertexAttribs = 0;
1903     glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
1904 
1905     for (GLint colorIndex = 0; colorIndex < maxVertexAttribs; ++colorIndex)
1906     {
1907         GLuint program = CompileProgram(kVS, kFS, [&](GLuint program) {
1908             glBindAttribLocation(program, colorIndex, "a_color");
1909         });
1910         ASSERT_NE(0u, program);
1911 
1912         drawQuad(program, "a_position", 0.5f);
1913         ASSERT_GL_NO_ERROR();
1914 
1915         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green) << "color index " << colorIndex;
1916 
1917         glDeleteProgram(program);
1918     }
1919 }
1920 
1921 // Test that draw with offset larger than vertex attribute's stride can work
TEST_P(VertexAttributeTest,DrawWithLargeBufferOffset)1922 TEST_P(VertexAttributeTest, DrawWithLargeBufferOffset)
1923 {
1924     constexpr size_t kBufferOffset    = 10000;
1925     constexpr size_t kQuadVertexCount = 4;
1926 
1927     std::array<GLbyte, kQuadVertexCount> validInputData = {{0, 1, 2, 3}};
1928 
1929     // 4 components
1930     std::array<GLbyte, 4 * kQuadVertexCount + kBufferOffset> inputData = {};
1931 
1932     std::array<GLfloat, 4 * kQuadVertexCount> expectedData;
1933     for (size_t i = 0; i < kQuadVertexCount; i++)
1934     {
1935         for (int j = 0; j < 4; ++j)
1936         {
1937             inputData[kBufferOffset + 4 * i + j] = validInputData[i];
1938             expectedData[4 * i + j]              = validInputData[i];
1939         }
1940     }
1941 
1942     initBasicProgram();
1943 
1944     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1945     glBufferData(GL_ARRAY_BUFFER, inputData.size(), inputData.data(), GL_STATIC_DRAW);
1946     glVertexAttribPointer(mTestAttrib, 4, GL_BYTE, GL_FALSE, 0,
1947                           reinterpret_cast<const void *>(kBufferOffset));
1948     glEnableVertexAttribArray(mTestAttrib);
1949     glBindBuffer(GL_ARRAY_BUFFER, 0);
1950 
1951     glVertexAttribPointer(mExpectedAttrib, 4, GL_FLOAT, GL_FALSE, 0, expectedData.data());
1952     glEnableVertexAttribArray(mExpectedAttrib);
1953 
1954     drawIndexedQuad(mProgram, "position", 0.5f);
1955 
1956     checkPixels();
1957 }
1958 
1959 // Test that drawing with large vertex attribute pointer offset and less components than
1960 // shader expects is OK
TEST_P(VertexAttributeTest,DrawWithLargeBufferOffsetAndLessComponents)1961 TEST_P(VertexAttributeTest, DrawWithLargeBufferOffsetAndLessComponents)
1962 {
1963     // Shader expects vec4 but glVertexAttribPointer only provides 2 components
1964     constexpr char kVS[] = R"(attribute vec4 a_position;
1965 attribute vec4 a_attrib;
1966 varying vec4 v_attrib;
1967 void main()
1968 {
1969     v_attrib = a_attrib;
1970     gl_Position = a_position;
1971 })";
1972 
1973     constexpr char kFS[] = R"(precision mediump float;
1974 varying vec4 v_attrib;
1975 void main()
1976 {
1977     gl_FragColor = v_attrib;
1978 })";
1979 
1980     ANGLE_GL_PROGRAM(program, kVS, kFS);
1981     glBindAttribLocation(program, 0, "a_position");
1982     glBindAttribLocation(program, 1, "a_attrib");
1983     glLinkProgram(program);
1984     glUseProgram(program);
1985     ASSERT_GL_NO_ERROR();
1986 
1987     constexpr size_t kBufferOffset = 4998;
1988 
1989     // Set up color data so yellow is drawn (only R, G components are provided)
1990     std::vector<GLushort> data(kBufferOffset + 12);
1991     for (int i = 0; i < 12; ++i)
1992     {
1993         data[kBufferOffset + i] = 0xffff;
1994     }
1995 
1996     GLBuffer buffer;
1997     glBindBuffer(GL_ARRAY_BUFFER, buffer);
1998     glBufferData(GL_ARRAY_BUFFER, sizeof(GLushort) * data.size(), data.data(), GL_STATIC_DRAW);
1999     // Provide only 2 components for the vec4 in the shader
2000     glVertexAttribPointer(1, 2, GL_UNSIGNED_SHORT, GL_TRUE, 0,
2001                           reinterpret_cast<const void *>(sizeof(GLushort) * kBufferOffset));
2002     glBindBuffer(GL_ARRAY_BUFFER, 0);
2003     glEnableVertexAttribArray(1);
2004 
2005     drawQuad(program, "a_position", 0.5f);
2006     // Verify yellow was drawn
2007     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
2008 }
2009 
2010 // Test that drawing with vertex attribute pointer with two non-overlapping BufferSubData calls
2011 // works correctly, especially when vertex conversion is involved.
TEST_P(VertexAttributeTest,DrawArraysWithNonOverlapBufferSubData)2012 TEST_P(VertexAttributeTest, DrawArraysWithNonOverlapBufferSubData)
2013 {
2014     constexpr size_t vertexCount = 6;
2015     initBasicProgram();
2016     glUseProgram(mProgram);
2017 
2018     // input data is GL_BYTEx3 (3 bytes) but stride=4
2019     std::array<GLbyte, 4 * vertexCount> inputData;
2020     std::array<GLfloat, 3 * vertexCount> expectedData;
2021     for (size_t i = 0; i < vertexCount; ++i)
2022     {
2023         inputData[4 * i]     = 3 * i;
2024         inputData[4 * i + 1] = 3 * i + 1;
2025         inputData[4 * i + 2] = 3 * i + 2;
2026 
2027         expectedData[3 * i]     = 3 * i;
2028         expectedData[3 * i + 1] = 3 * i + 1;
2029         expectedData[3 * i + 2] = 3 * i + 2;
2030     }
2031 
2032     GLBuffer quadBuffer;
2033     InitQuadVertexBuffer(&quadBuffer);
2034     GLint positionLocation = glGetAttribLocation(mProgram, "position");
2035     ASSERT_NE(-1, positionLocation);
2036     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2037     glEnableVertexAttribArray(positionLocation);
2038 
2039     GLsizei fullDataSize = 4 * vertexCount;
2040     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
2041     glBufferData(GL_ARRAY_BUFFER, fullDataSize, nullptr, GL_STATIC_DRAW);
2042     glBufferSubData(GL_ARRAY_BUFFER, 0, fullDataSize, inputData.data());
2043     glVertexAttribPointer(mTestAttrib, 3, GL_BYTE, GL_FALSE, /* stride */ 4, nullptr);
2044     glEnableVertexAttribArray(mTestAttrib);
2045 
2046     glBindBuffer(GL_ARRAY_BUFFER, 0);
2047     glVertexAttribPointer(mExpectedAttrib, 3, GL_FLOAT, GL_FALSE, 0, expectedData.data());
2048     glEnableVertexAttribArray(mExpectedAttrib);
2049 
2050     // Draw quad and verify data
2051     glClearColor(0, 0, 0, 0);
2052     glClear(GL_COLOR_BUFFER_BIT);
2053     glDrawArrays(GL_TRIANGLES, 0, vertexCount);
2054     checkPixels();
2055 
2056     // Update data with two non-overlapping BufferSubData calls with different set of data
2057     for (size_t i = 0; i < vertexCount; ++i)
2058     {
2059         inputData[4 * i]     = 3 * (i + vertexCount);
2060         inputData[4 * i + 1] = 3 * (i + vertexCount) + 1;
2061         inputData[4 * i + 2] = 3 * (i + vertexCount) + 2;
2062 
2063         expectedData[3 * i]     = 3 * (i + vertexCount);
2064         expectedData[3 * i + 1] = 3 * (i + vertexCount) + 1;
2065         expectedData[3 * i + 2] = 3 * (i + vertexCount) + 2;
2066     }
2067     size_t halfDataSize = fullDataSize / 2;
2068     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
2069     glBufferSubData(GL_ARRAY_BUFFER, 0, halfDataSize, inputData.data());
2070     glBufferSubData(GL_ARRAY_BUFFER, halfDataSize, fullDataSize - halfDataSize,
2071                     inputData.data() + halfDataSize);
2072     glBindBuffer(GL_ARRAY_BUFFER, 0);
2073     glVertexAttribPointer(mExpectedAttrib, 3, GL_FLOAT, GL_FALSE, 0, expectedData.data());
2074 
2075     // Draw quad and verify data
2076     glDrawArrays(GL_TRIANGLES, 0, 6);
2077     checkPixels();
2078 
2079     EXPECT_GL_NO_ERROR();
2080 }
2081 
2082 // Test that drawing with vertex attribute pointer with two overlapping BufferSubData calls works
2083 // correctly, especially when vertex conversion is involved.
TEST_P(VertexAttributeTest,DrawArraysWithOverlapBufferSubData)2084 TEST_P(VertexAttributeTest, DrawArraysWithOverlapBufferSubData)
2085 {
2086     constexpr size_t vertexCount = 6;
2087     initBasicProgram();
2088     glUseProgram(mProgram);
2089 
2090     // input data is GL_BYTEx3 (3 bytes) but stride=4
2091     std::array<GLbyte, 4 * vertexCount> inputData;
2092     std::array<GLfloat, 3 * vertexCount> expectedData;
2093     for (size_t i = 0; i < vertexCount; ++i)
2094     {
2095         inputData[4 * i]     = 3 * i;
2096         inputData[4 * i + 1] = 3 * i + 1;
2097         inputData[4 * i + 2] = 3 * i + 2;
2098 
2099         expectedData[3 * i]     = 3 * i;
2100         expectedData[3 * i + 1] = 3 * i + 1;
2101         expectedData[3 * i + 2] = 3 * i + 2;
2102     }
2103 
2104     GLBuffer quadBuffer;
2105     InitQuadVertexBuffer(&quadBuffer);
2106     GLint positionLocation = glGetAttribLocation(mProgram, "position");
2107     ASSERT_NE(-1, positionLocation);
2108     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2109     glEnableVertexAttribArray(positionLocation);
2110 
2111     GLsizei fullDataSize = 4 * vertexCount;
2112     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
2113     glBufferData(GL_ARRAY_BUFFER, fullDataSize, nullptr, GL_STATIC_DRAW);
2114     glBufferSubData(GL_ARRAY_BUFFER, 0, fullDataSize, inputData.data());
2115     glVertexAttribPointer(mTestAttrib, 3, GL_BYTE, GL_FALSE, /* stride */ 4, nullptr);
2116     glEnableVertexAttribArray(mTestAttrib);
2117 
2118     glBindBuffer(GL_ARRAY_BUFFER, 0);
2119     glVertexAttribPointer(mExpectedAttrib, 3, GL_FLOAT, GL_FALSE, 0, expectedData.data());
2120     glEnableVertexAttribArray(mExpectedAttrib);
2121 
2122     // Draw quad and verify data
2123     glClearColor(0, 0, 0, 0);
2124     glClear(GL_COLOR_BUFFER_BIT);
2125     glDrawArrays(GL_TRIANGLES, 0, vertexCount);
2126     checkPixels();
2127 
2128     // Update data with two overlapping BufferSubData calls with different set of data.
2129     size_t halfVertexCount = vertexCount / 2;
2130     size_t quadDataSize    = fullDataSize / 4;
2131     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
2132     // First subData is for the first 3 quarter of buffer, but only first half contains valid data.
2133     for (size_t i = 0; i < vertexCount; ++i)
2134     {
2135         if (i < halfVertexCount)
2136         {
2137             inputData[4 * i]     = 3 * (i + vertexCount);
2138             inputData[4 * i + 1] = 3 * (i + vertexCount) + 1;
2139             inputData[4 * i + 2] = 3 * (i + vertexCount) + 2;
2140         }
2141         else
2142         {
2143             inputData[4 * i]     = 0;
2144             inputData[4 * i + 1] = 0;
2145             inputData[4 * i + 2] = 0;
2146         }
2147 
2148         expectedData[3 * i]     = 3 * (i + vertexCount);
2149         expectedData[3 * i + 1] = 3 * (i + vertexCount) + 1;
2150         expectedData[3 * i + 2] = 3 * (i + vertexCount) + 2;
2151     }
2152     glBufferSubData(GL_ARRAY_BUFFER, 0, 3 * quadDataSize, inputData.data());
2153     // Second subData call is for the last half buffer, which overlaps with previous subData range.
2154     size_t halfDataSize = fullDataSize / 2;
2155     for (size_t i = halfVertexCount; i < vertexCount; ++i)
2156     {
2157         inputData[4 * i]     = 3 * (i + vertexCount);
2158         inputData[4 * i + 1] = 3 * (i + vertexCount) + 1;
2159         inputData[4 * i + 2] = 3 * (i + vertexCount) + 2;
2160     }
2161     glBufferSubData(GL_ARRAY_BUFFER, halfDataSize, fullDataSize - halfDataSize,
2162                     inputData.data() + halfDataSize);
2163     glBindBuffer(GL_ARRAY_BUFFER, 0);
2164     glVertexAttribPointer(mExpectedAttrib, 3, GL_FLOAT, GL_FALSE, 0, expectedData.data());
2165 
2166     // Draw quad and verify data
2167     glDrawArrays(GL_TRIANGLES, 0, 6);
2168     checkPixels();
2169 
2170     EXPECT_GL_NO_ERROR();
2171 }
2172 
2173 // Test that drawing with vertex attribute pointer with different offset. The second offset is
2174 // multiple stride after first offset.
TEST_P(VertexAttributeTest,DrawArraysWithLargerBindingOffset)2175 TEST_P(VertexAttributeTest, DrawArraysWithLargerBindingOffset)
2176 {
2177     constexpr size_t vertexCount = 6;
2178     initBasicProgram();
2179     glUseProgram(mProgram);
2180 
2181     // input data is GL_BYTEx3 (3 bytes) but stride=4
2182     std::array<GLbyte, 4 * vertexCount * 2> inputData;
2183     std::array<GLfloat, 3 * vertexCount * 2> expectedData;
2184     for (size_t i = 0; i < vertexCount * 2; ++i)
2185     {
2186         inputData[4 * i]     = 3 * i;
2187         inputData[4 * i + 1] = 3 * i + 1;
2188         inputData[4 * i + 2] = 3 * i + 2;
2189 
2190         expectedData[3 * i]     = 3 * i;
2191         expectedData[3 * i + 1] = 3 * i + 1;
2192         expectedData[3 * i + 2] = 3 * i + 2;
2193     }
2194 
2195     GLBuffer quadBuffer;
2196     InitQuadVertexBuffer(&quadBuffer);
2197     GLint positionLocation = glGetAttribLocation(mProgram, "position");
2198     ASSERT_NE(-1, positionLocation);
2199     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2200     glEnableVertexAttribArray(positionLocation);
2201 
2202     GLsizei fullDataSize = 4 * vertexCount * 2;
2203     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
2204     glBufferData(GL_ARRAY_BUFFER, fullDataSize, nullptr, GL_STATIC_DRAW);
2205     glBufferSubData(GL_ARRAY_BUFFER, 0, fullDataSize, inputData.data());
2206     glVertexAttribPointer(mTestAttrib, 3, GL_BYTE, GL_FALSE, /* stride */ 4, /*offset*/ nullptr);
2207     glEnableVertexAttribArray(mTestAttrib);
2208 
2209     glBindBuffer(GL_ARRAY_BUFFER, 0);
2210     glVertexAttribPointer(mExpectedAttrib, 3, GL_FLOAT, GL_FALSE, 0, /*data*/ expectedData.data());
2211     glEnableVertexAttribArray(mExpectedAttrib);
2212 
2213     // Draw quad and verify data
2214     glClearColor(0, 0, 0, 0);
2215     glClear(GL_COLOR_BUFFER_BIT);
2216     glDrawArrays(GL_TRIANGLES, 0, vertexCount);
2217     checkPixels();
2218 
2219     // Now bind to a larger offset and then draw and verify
2220     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
2221     glVertexAttribPointer(mTestAttrib, 3, GL_BYTE, GL_FALSE, /* stride */ 4,
2222                           reinterpret_cast<const void *>(4 * vertexCount));
2223     glBindBuffer(GL_ARRAY_BUFFER, 0);
2224     glVertexAttribPointer(mExpectedAttrib, 3, GL_FLOAT, GL_FALSE, 0,
2225                           expectedData.data() + 3 * vertexCount);
2226     // Draw quad and verify data
2227     glDrawArrays(GL_TRIANGLES, 0, vertexCount);
2228     checkPixels();
2229 
2230     EXPECT_GL_NO_ERROR();
2231 }
2232 
2233 // Test that drawing with vertex attribute pointer with different offset. The second offset is
2234 // multiple stride before first offset.
TEST_P(VertexAttributeTest,DrawArraysWithSmallerBindingOffset)2235 TEST_P(VertexAttributeTest, DrawArraysWithSmallerBindingOffset)
2236 {
2237     constexpr size_t vertexCount = 6;
2238     initBasicProgram();
2239     glUseProgram(mProgram);
2240 
2241     // input data is GL_BYTEx3 (3 bytes) but stride=4
2242     std::array<GLbyte, 4 * vertexCount * 2> inputData;
2243     std::array<GLfloat, 3 * vertexCount * 2> expectedData;
2244     for (size_t i = 0; i < vertexCount * 2; ++i)
2245     {
2246         inputData[4 * i]     = 3 * i;
2247         inputData[4 * i + 1] = 3 * i + 1;
2248         inputData[4 * i + 2] = 3 * i + 2;
2249 
2250         expectedData[3 * i]     = 3 * i;
2251         expectedData[3 * i + 1] = 3 * i + 1;
2252         expectedData[3 * i + 2] = 3 * i + 2;
2253     }
2254 
2255     GLBuffer quadBuffer;
2256     InitQuadVertexBuffer(&quadBuffer);
2257     GLint positionLocation = glGetAttribLocation(mProgram, "position");
2258     ASSERT_NE(-1, positionLocation);
2259     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2260     glEnableVertexAttribArray(positionLocation);
2261 
2262     GLsizei fullDataSize = 4 * vertexCount * 2;
2263     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
2264     glBufferData(GL_ARRAY_BUFFER, fullDataSize, nullptr, GL_STATIC_DRAW);
2265     glBufferSubData(GL_ARRAY_BUFFER, 0, fullDataSize, inputData.data());
2266     glVertexAttribPointer(mTestAttrib, 3, GL_BYTE, GL_FALSE, /* stride */ 4,
2267                           reinterpret_cast<const void *>(4 * vertexCount));
2268     glEnableVertexAttribArray(mTestAttrib);
2269 
2270     glBindBuffer(GL_ARRAY_BUFFER, 0);
2271     glVertexAttribPointer(mExpectedAttrib, 3, GL_FLOAT, GL_FALSE, 0,
2272                           expectedData.data() + 3 * vertexCount);
2273     glEnableVertexAttribArray(mExpectedAttrib);
2274 
2275     // Draw quad and verify data
2276     glClearColor(0, 0, 0, 0);
2277     glClear(GL_COLOR_BUFFER_BIT);
2278     glDrawArrays(GL_TRIANGLES, 0, vertexCount);
2279     checkPixels();
2280 
2281     // Now bind to a smaller offset and draw and verify.
2282     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
2283     glVertexAttribPointer(mTestAttrib, 3, GL_BYTE, GL_FALSE, /* stride */ 4, /*offset*/ nullptr);
2284     glBindBuffer(GL_ARRAY_BUFFER, 0);
2285     glVertexAttribPointer(mExpectedAttrib, 3, GL_FLOAT, GL_FALSE, 0, /*data*/ expectedData.data());
2286     // Draw quad and verify data
2287     glDrawArrays(GL_TRIANGLES, 0, vertexCount);
2288     checkPixels();
2289 
2290     EXPECT_GL_NO_ERROR();
2291 }
2292 
2293 // Tests that we do not generate a SIGBUS error on arm when translating unaligned data.
2294 // GL_RG32_SNORM_ANGLEX is used when using glVertexAttribPointer with certain parameters.
TEST_P(VertexAttributeTestES3,DrawWithUnalignedData)2295 TEST_P(VertexAttributeTestES3, DrawWithUnalignedData)
2296 {
2297     constexpr char kVS[] = R"(#version 300 es
2298 precision highp float;
2299 in highp vec4 a_position;
2300 in highp vec2 a_ColorTest;
2301 out highp vec2 v_colorTest;
2302 
2303 void main() {
2304     v_colorTest = a_ColorTest;
2305     gl_Position = a_position;
2306 })";
2307 
2308     constexpr char kFS[] = R"(#version 300 es
2309 precision highp float;
2310 in highp vec2 v_colorTest;
2311 out vec4 fragColor;
2312 
2313 void main() {
2314     // The input value is 0x01000000 / 0x7FFFFFFF
2315     if(abs(v_colorTest.x - 0.0078125) < 0.001) {
2316         fragColor = vec4(0.0, 1.0, 0.0, 1.0);
2317     } else {
2318         fragColor = vec4(1.0, 0.0, 0.0, 1.0);
2319     }
2320 })";
2321 
2322     ANGLE_GL_PROGRAM(program, kVS, kFS);
2323     glBindAttribLocation(program, 0, "a_position");
2324     glBindAttribLocation(program, 1, "a_ColorTest");
2325     glLinkProgram(program);
2326     glUseProgram(program);
2327     ASSERT_GL_NO_ERROR();
2328 
2329     constexpr size_t kDataSize = 12;
2330 
2331     // Initialize vertex attribute data with 1u32s, but shifted right by a variable number of bytes
2332     GLubyte colorTestData[(kDataSize + 1) * sizeof(GLuint)];
2333 
2334     for (size_t offset = 0; offset < sizeof(GLuint); offset++)
2335     {
2336         for (size_t dataIndex = 0; dataIndex < kDataSize * sizeof(GLuint); dataIndex++)
2337         {
2338             if (dataIndex % sizeof(GLuint) == sizeof(GLuint) - 1)
2339             {
2340                 colorTestData[dataIndex + offset] = 1;
2341             }
2342             else
2343             {
2344 
2345                 colorTestData[dataIndex + offset] = 0;
2346             }
2347         }
2348 
2349         GLubyte *offsetPtr = &colorTestData[offset];
2350         glVertexAttribPointer(1, 2, GL_INT, GL_TRUE, sizeof(GLuint), offsetPtr);
2351 
2352         glBindBuffer(GL_ARRAY_BUFFER, 0);
2353         glEnableVertexAttribArray(1);
2354 
2355         drawIndexedQuad(program, "a_position", 0.5f, 1.0f, false, true);
2356 
2357         // Verify green was drawn.
2358         EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
2359         ASSERT_GL_NO_ERROR();
2360     }
2361 }
2362 
2363 // Tests that rendering is fine if GL_ANGLE_relaxed_vertex_attribute_type is enabled
2364 // and mismatched integer signedness between the program's attribute type and the
2365 // attribute type specified by VertexAttribIPointer are used.
TEST_P(VertexAttributeTestES3,DrawWithRelaxedVertexAttributeType)2366 TEST_P(VertexAttributeTestES3, DrawWithRelaxedVertexAttributeType)
2367 {
2368     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_relaxed_vertex_attribute_type"));
2369 
2370     constexpr char kVS[] = R"(#version 300 es
2371 precision highp float;
2372 in highp vec4 a_position;
2373 in highp ivec4 a_ColorTest;
2374 out highp vec4 v_colorTest;
2375 
2376 void main() {
2377     v_colorTest = vec4(a_ColorTest);
2378     gl_Position = a_position;
2379 })";
2380 
2381     constexpr char kFS[] = R"(#version 300 es
2382 precision highp float;
2383 in highp vec4 v_colorTest;
2384 out vec4 fragColor;
2385 
2386 void main() {
2387     if(v_colorTest.x > 0.5) {
2388         fragColor = vec4(0.0, 1.0, 0.0, 1.0);
2389     } else {
2390         fragColor = vec4(1.0, 0.0, 0.0, 1.0);
2391     }
2392 })";
2393 
2394     ANGLE_GL_PROGRAM(program, kVS, kFS);
2395     glBindAttribLocation(program, 0, "a_position");
2396     glBindAttribLocation(program, 1, "a_ColorTest");
2397     glLinkProgram(program);
2398     glUseProgram(program);
2399     ASSERT_GL_NO_ERROR();
2400 
2401     constexpr size_t kDataSize = 48;
2402 
2403     // Interleave test data with 0's.
2404     // This guards against a future code change that adjusts stride to 0
2405 
2406     // clang-format off
2407     constexpr GLuint kColorTestData[kDataSize] = {
2408         // Vertex attribute data      Unused data
2409         0u, 0u, 0u, 0u, /*red*/       0u, 0u, 0u, 0u,
2410         1u, 1u, 1u, 1u,               0u, 0u, 0u, 0u,
2411         1u, 1u, 1u, 1u,               0u, 0u, 0u, 0u,
2412         1u, 1u, 1u, 1u,               0u, 0u, 0u, 0u,
2413         1u, 1u, 1u, 1u,               0u, 0u, 0u, 0u,
2414         1u, 1u, 1u, 1u,               0u, 0u, 0u, 0u
2415     };
2416     // clang-format on
2417 
2418     GLBuffer buffer;
2419     glBindBuffer(GL_ARRAY_BUFFER, buffer);
2420     glBufferData(GL_ARRAY_BUFFER, sizeof(GLuint) * kDataSize, kColorTestData, GL_STATIC_DRAW);
2421 
2422     glVertexAttribIPointer(1, 4, GL_UNSIGNED_INT, 8 * sizeof(GLuint),
2423                            reinterpret_cast<const void *>(0));
2424 
2425     glBindBuffer(GL_ARRAY_BUFFER, 0);
2426     glEnableVertexAttribArray(1);
2427 
2428     drawQuad(program, "a_position", 0.5f);
2429 
2430     // Verify green was drawn. If the stride isn't adjusted to 0 this corner will be green. If it is
2431     // adjusted to 0, the whole image will be red
2432     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
2433     ASSERT_GL_NO_ERROR();
2434 }
2435 
2436 // Test that ensures we do not send data for components not specified by glVertexAttribPointer when
2437 // component types and sizes are mismatched
TEST_P(VertexAttributeTestES3,DrawWithMismatchedComponentCount)2438 TEST_P(VertexAttributeTestES3, DrawWithMismatchedComponentCount)
2439 {
2440     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_relaxed_vertex_attribute_type"));
2441 
2442     // To ensure the test results are valid when we don't send data for every component, the
2443     // shader's values must be defined by the backend.
2444     // Vulkan Spec 22.3. Vertex Attribute Divisor in Instanced Rendering
2445     // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#_vertex_attribute_divisor_in_instanced_rendering
2446     // If the format does not include G, B, or A components, then those are filled with (0,0,1) as
2447     // needed (using either 1.0f or integer 1 based on the format) for attributes that are not
2448     // 64-bit data types.
2449     ANGLE_SKIP_TEST_IF(!IsVulkan());
2450 
2451     constexpr char kVS[] = R"(#version 300 es
2452 precision highp float;
2453 in highp vec4 a_position;
2454 in highp ivec2 a_ColorTest;
2455 out highp vec2 v_colorTest;
2456 
2457 void main() {
2458     v_colorTest = vec2(a_ColorTest);
2459     gl_Position = a_position;
2460 })";
2461 
2462     constexpr char kFS[] = R"(#version 300 es
2463 precision highp float;
2464 in highp vec2 v_colorTest;
2465 out vec4 fragColor;
2466 
2467 void main() {
2468     if(v_colorTest.y < 0.5) {
2469         fragColor = vec4(0.0, 1.0, 0.0, 1.0);
2470     } else {
2471         fragColor = vec4(1.0, 0.0, 0.0, 1.0);
2472     }
2473 })";
2474 
2475     ANGLE_GL_PROGRAM(program, kVS, kFS);
2476     glBindAttribLocation(program, 0, "a_position");
2477     glBindAttribLocation(program, 1, "a_ColorTest");
2478     glLinkProgram(program);
2479     glUseProgram(program);
2480     ASSERT_GL_NO_ERROR();
2481 
2482     constexpr size_t kDataSize = 24;
2483 
2484     // Initialize vertex attribute data with 1s.
2485     GLuint kColorTestData[kDataSize];
2486     for (size_t dataIndex = 0; dataIndex < kDataSize; dataIndex++)
2487     {
2488         kColorTestData[dataIndex] = 1u;
2489     }
2490 
2491     GLBuffer buffer;
2492     glBindBuffer(GL_ARRAY_BUFFER, buffer);
2493     glBufferData(GL_ARRAY_BUFFER, sizeof(GLuint) * kDataSize, kColorTestData, GL_STATIC_DRAW);
2494 
2495     glVertexAttribIPointer(1, 1, GL_UNSIGNED_INT, 4 * sizeof(GLuint),
2496                            reinterpret_cast<const void *>(0));
2497 
2498     glBindBuffer(GL_ARRAY_BUFFER, 0);
2499     glEnableVertexAttribArray(1);
2500 
2501     drawQuad(program, "a_position", 0.5f);
2502 
2503     // Verify green was drawn.
2504     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::green);
2505     ASSERT_GL_NO_ERROR();
2506 }
2507 
2508 // Test that ensures we do not send data for components not specified by glVertexAttribPointer when
2509 // component types and sizes are mismatched. Also guard against out of bound errors when atttribute
2510 // locations are specified.
TEST_P(VertexAttributeTestES3,DrawWithMismatchedComponentCountLocationSpecified)2511 TEST_P(VertexAttributeTestES3, DrawWithMismatchedComponentCountLocationSpecified)
2512 {
2513     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_relaxed_vertex_attribute_type"));
2514 
2515     // To ensure the test results are valid when we don't send data for every component, the
2516     // shader's values must be defined by the backend.
2517     // Vulkan Spec 22.3. Vertex Attribute Divisor in Instanced Rendering
2518     // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#_vertex_attribute_divisor_in_instanced_rendering
2519     // If the format does not include G, B, or A components, then those are filled with (0,0,1) as
2520     // needed (using either 1.0f or integer 1 based on the format) for attributes that are not
2521     // 64-bit data types.
2522     ANGLE_SKIP_TEST_IF(!IsVulkan());
2523 
2524     constexpr char kVS[] = R"(#version 300 es
2525 precision highp float;
2526 layout(location = 2) in highp vec4 a_position;
2527 layout(location = 0) in highp ivec2 a_ColorTest;
2528 out highp vec2 v_colorTest;
2529 
2530 void main() {
2531     v_colorTest = vec2(a_ColorTest);
2532     gl_Position = a_position;
2533 })";
2534 
2535     constexpr char kFS[] = R"(#version 300 es
2536 precision highp float;
2537 in highp vec2 v_colorTest;
2538 out vec4 fragColor;
2539 
2540 void main() {
2541     if(v_colorTest.y < 0.5) {
2542         fragColor = vec4(0.0, 1.0, 0.0, 1.0);
2543     } else {
2544         fragColor = vec4(1.0, 0.0, 0.0, 1.0);
2545     }
2546 })";
2547 
2548     ANGLE_GL_PROGRAM(program, kVS, kFS);
2549     glLinkProgram(program);
2550     glUseProgram(program);
2551     ASSERT_GL_NO_ERROR();
2552 
2553     constexpr size_t kDataSize = 24;
2554 
2555     // Initialize vertex attribute data with 1s.
2556     GLuint kColorTestData[kDataSize];
2557     for (size_t dataIndex = 0; dataIndex < kDataSize; dataIndex++)
2558     {
2559         kColorTestData[dataIndex] = 1u;
2560     }
2561 
2562     GLBuffer buffer;
2563     glBindBuffer(GL_ARRAY_BUFFER, buffer);
2564     glBufferData(GL_ARRAY_BUFFER, sizeof(GLuint) * kDataSize, kColorTestData, GL_STATIC_DRAW);
2565 
2566     GLint colorLocation = glGetAttribLocation(program, "a_ColorTest");
2567     ASSERT_NE(colorLocation, -1);
2568     glVertexAttribIPointer(colorLocation, 1, GL_UNSIGNED_INT, 4 * sizeof(GLuint),
2569                            reinterpret_cast<const void *>(0));
2570 
2571     glBindBuffer(GL_ARRAY_BUFFER, 0);
2572     glEnableVertexAttribArray(1);
2573 
2574     drawQuad(program, "a_position", 0.5f);
2575 
2576     // Verify green was drawn.
2577     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::green);
2578     ASSERT_GL_NO_ERROR();
2579 }
2580 
2581 class VertexAttributeTestES31 : public VertexAttributeTestES3
2582 {
2583   protected:
VertexAttributeTestES31()2584     VertexAttributeTestES31() {}
2585 
initTest()2586     void initTest()
2587     {
2588         initBasicProgram();
2589         glUseProgram(mProgram);
2590 
2591         glGenVertexArrays(1, &mVAO);
2592         glBindVertexArray(mVAO);
2593 
2594         auto quadVertices = GetQuadVertices();
2595         GLsizeiptr quadVerticesSize =
2596             static_cast<GLsizeiptr>(quadVertices.size() * sizeof(quadVertices[0]));
2597         glGenBuffers(1, &mQuadBuffer);
2598         glBindBuffer(GL_ARRAY_BUFFER, mQuadBuffer);
2599         glBufferData(GL_ARRAY_BUFFER, quadVerticesSize, quadVertices.data(), GL_STATIC_DRAW);
2600 
2601         GLint positionLocation = glGetAttribLocation(mProgram, "position");
2602         ASSERT_NE(-1, positionLocation);
2603         glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2604         glEnableVertexAttribArray(positionLocation);
2605 
2606         std::array<GLfloat, kVertexCount> expectedData;
2607         for (size_t count = 0; count < kVertexCount; ++count)
2608         {
2609             expectedData[count] = static_cast<GLfloat>(count);
2610         }
2611 
2612         const GLsizei kExpectedDataSize = kVertexCount * kFloatStride;
2613         glGenBuffers(1, &mExpectedBuffer);
2614         glBindBuffer(GL_ARRAY_BUFFER, mExpectedBuffer);
2615         glBufferData(GL_ARRAY_BUFFER, kExpectedDataSize, expectedData.data(), GL_STATIC_DRAW);
2616         glVertexAttribPointer(mExpectedAttrib, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
2617         glEnableVertexAttribArray(mExpectedAttrib);
2618     }
2619 
testTearDown()2620     void testTearDown() override
2621     {
2622         VertexAttributeTestES3::testTearDown();
2623 
2624         glDeleteBuffers(1, &mQuadBuffer);
2625         glDeleteBuffers(1, &mExpectedBuffer);
2626         glDeleteVertexArrays(1, &mVAO);
2627     }
2628 
drawArraysWithStrideAndRelativeOffset(GLint stride,GLuint relativeOffset)2629     void drawArraysWithStrideAndRelativeOffset(GLint stride, GLuint relativeOffset)
2630     {
2631         initTest();
2632 
2633         GLint floatStride          = std::max(stride / kFloatStride, 1);
2634         GLuint floatRelativeOffset = relativeOffset / kFloatStride;
2635         size_t floatCount = static_cast<size_t>(floatRelativeOffset) + kVertexCount * floatStride;
2636         GLsizeiptr inputSize = static_cast<GLsizeiptr>(floatCount) * kFloatStride;
2637 
2638         std::vector<GLfloat> inputData(floatCount);
2639         for (size_t count = 0; count < kVertexCount; ++count)
2640         {
2641             inputData[floatRelativeOffset + count * floatStride] = static_cast<GLfloat>(count);
2642         }
2643 
2644         // Ensure inputSize, inputStride and inputOffset are multiples of TypeStride(GL_FLOAT).
2645         GLsizei inputStride            = floatStride * kFloatStride;
2646         GLsizeiptr inputRelativeOffset = floatRelativeOffset * kFloatStride;
2647         glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
2648         glBufferData(GL_ARRAY_BUFFER, inputSize, nullptr, GL_STATIC_DRAW);
2649         glBufferSubData(GL_ARRAY_BUFFER, 0, inputSize, inputData.data());
2650         glVertexAttribFormat(mTestAttrib, 1, GL_FLOAT, GL_FALSE,
2651                              base::checked_cast<GLuint>(inputRelativeOffset));
2652         glBindVertexBuffer(mTestAttrib, mBuffer, 0, inputStride);
2653         glEnableVertexAttribArray(mTestAttrib);
2654 
2655         glDrawArrays(GL_TRIANGLES, 0, 6);
2656         checkPixels();
2657 
2658         EXPECT_GL_NO_ERROR();
2659     }
2660 
initOnlyUpdateBindingTest(GLint bindingToUpdate)2661     void initOnlyUpdateBindingTest(GLint bindingToUpdate)
2662     {
2663         initTest();
2664 
2665         constexpr GLuint kTestFloatOffset1                               = kVertexCount;
2666         std::array<GLfloat, kTestFloatOffset1 + kVertexCount> inputData1 = {};
2667         for (size_t count = 0; count < kVertexCount; ++count)
2668         {
2669             GLfloat value                         = static_cast<GLfloat>(count);
2670             inputData1[kTestFloatOffset1 + count] = value;
2671         }
2672 
2673         GLBuffer testBuffer1;
2674         glBindBuffer(GL_ARRAY_BUFFER, testBuffer1);
2675         glBufferData(GL_ARRAY_BUFFER, inputData1.size() * kFloatStride, inputData1.data(),
2676                      GL_STATIC_DRAW);
2677 
2678         ASSERT_NE(bindingToUpdate, mTestAttrib);
2679         ASSERT_NE(bindingToUpdate, mExpectedAttrib);
2680 
2681         // Set mTestAttrib using the binding bindingToUpdate.
2682         glVertexAttribFormat(mTestAttrib, 1, GL_FLOAT, GL_FALSE, 0);
2683         glBindVertexBuffer(bindingToUpdate, testBuffer1, kTestFloatOffset1 * kFloatStride,
2684                            kFloatStride);
2685         glVertexAttribBinding(mTestAttrib, bindingToUpdate);
2686         glEnableVertexAttribArray(mTestAttrib);
2687 
2688         // In the first draw the current VAO states are set to driver.
2689         glDrawArrays(GL_TRIANGLES, 0, 6);
2690         checkPixels();
2691         EXPECT_GL_NO_ERROR();
2692 
2693         // We need the second draw to ensure all VAO dirty bits are reset.
2694         // e.g. On D3D11 back-ends, Buffer11::resize is called in the first draw, where the related
2695         // binding is set to dirty again.
2696         glDrawArrays(GL_TRIANGLES, 0, 6);
2697         checkPixels();
2698         EXPECT_GL_NO_ERROR();
2699     }
2700 
2701     std::string makeMismatchingSignsTestVS(uint32_t attribCount, uint16_t signedMask);
2702     std::string makeMismatchingSignsTestFS(uint32_t attribCount);
2703     uint16_t setupVertexAttribPointersForMismatchSignsTest(uint16_t currentSignedMask,
2704                                                            uint16_t toggleMask);
2705 
2706     GLuint mVAO            = 0;
2707     GLuint mExpectedBuffer = 0;
2708     GLuint mQuadBuffer     = 0;
2709 
2710     const GLsizei kFloatStride = TypeStride(GL_FLOAT);
2711 
2712     // Set the maximum value for stride and relativeOffset in case they are too large.
2713     const GLint MAX_STRIDE_FOR_TEST          = 4095;
2714     const GLint MAX_RELATIVE_OFFSET_FOR_TEST = 4095;
2715 };
2716 
2717 // Verify that MAX_VERTEX_ATTRIB_STRIDE is no less than the minimum required value (2048) in ES3.1.
TEST_P(VertexAttributeTestES31,MaxVertexAttribStride)2718 TEST_P(VertexAttributeTestES31, MaxVertexAttribStride)
2719 {
2720     GLint maxStride;
2721     glGetIntegerv(GL_MAX_VERTEX_ATTRIB_STRIDE, &maxStride);
2722     ASSERT_GL_NO_ERROR();
2723 
2724     EXPECT_GE(maxStride, 2048);
2725 }
2726 
2727 // Verify that GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET is no less than the minimum required value
2728 // (2047) in ES3.1.
TEST_P(VertexAttributeTestES31,MaxVertexAttribRelativeOffset)2729 TEST_P(VertexAttributeTestES31, MaxVertexAttribRelativeOffset)
2730 {
2731     GLint maxRelativeOffset;
2732     glGetIntegerv(GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET, &maxRelativeOffset);
2733     ASSERT_GL_NO_ERROR();
2734 
2735     EXPECT_GE(maxRelativeOffset, 2047);
2736 }
2737 
2738 // Verify using MAX_VERTEX_ATTRIB_STRIDE as stride doesn't mess up the draw.
2739 // Use default value if the value of MAX_VERTEX_ATTRIB_STRIDE is too large for this test.
TEST_P(VertexAttributeTestES31,DrawArraysWithLargeStride)2740 TEST_P(VertexAttributeTestES31, DrawArraysWithLargeStride)
2741 {
2742     GLint maxStride;
2743     glGetIntegerv(GL_MAX_VERTEX_ATTRIB_STRIDE, &maxStride);
2744     ASSERT_GL_NO_ERROR();
2745 
2746     GLint largeStride = std::min(maxStride, MAX_STRIDE_FOR_TEST);
2747     drawArraysWithStrideAndRelativeOffset(largeStride, 0);
2748 }
2749 
2750 // Verify using MAX_VERTEX_ATTRIB_RELATIVE_OFFSET as relativeOffset doesn't mess up the draw.
2751 // Use default value if the value of MAX_VERTEX_ATTRIB_RELATIVE_OFFSSET is too large for this test.
TEST_P(VertexAttributeTestES31,DrawArraysWithLargeRelativeOffset)2752 TEST_P(VertexAttributeTestES31, DrawArraysWithLargeRelativeOffset)
2753 {
2754     GLint maxRelativeOffset;
2755     glGetIntegerv(GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET, &maxRelativeOffset);
2756     ASSERT_GL_NO_ERROR();
2757 
2758     GLint largeRelativeOffset = std::min(maxRelativeOffset, MAX_RELATIVE_OFFSET_FOR_TEST);
2759     drawArraysWithStrideAndRelativeOffset(0, largeRelativeOffset);
2760 }
2761 
2762 // Test that vertex array object works correctly when render pipeline and compute pipeline are
2763 // crossly executed.
TEST_P(VertexAttributeTestES31,MixedComputeAndRenderPipelines)2764 TEST_P(VertexAttributeTestES31, MixedComputeAndRenderPipelines)
2765 {
2766     constexpr char kComputeShader[] =
2767         R"(#version 310 es
2768 layout(local_size_x=1) in;
2769 void main()
2770 {
2771 })";
2772     ANGLE_GL_COMPUTE_PROGRAM(computeProgram, kComputeShader);
2773 
2774     glViewport(0, 0, getWindowWidth(), getWindowHeight());
2775     glClearColor(0, 0, 0, 0);
2776 
2777     constexpr char kVertexShader[] =
2778         R"(#version 310 es
2779 precision mediump float;
2780 layout(location = 0) in vec4 position;
2781 layout(location = 2) in vec2 aOffset;
2782 layout(location = 3) in vec4 aColor;
2783 out vec4 vColor;
2784 void main() {
2785     vColor = aColor;
2786     gl_Position = position + vec4(aOffset, 0.0, 0.0);
2787 })";
2788 
2789     constexpr char kFragmentShader[] =
2790         R"(#version 310 es
2791 precision mediump float;
2792 in vec4 vColor;
2793 out vec4  color;
2794 void main() {
2795     color = vColor;
2796 })";
2797 
2798     ANGLE_GL_PROGRAM(renderProgram, kVertexShader, kFragmentShader);
2799 
2800     constexpr char kVertexShader1[] =
2801         R"(#version 310 es
2802 precision mediump float;
2803 layout(location = 1) in vec4 position;
2804 layout(location = 2) in vec2 aOffset;
2805 layout(location = 3) in vec4 aColor;
2806 out vec4 vColor;
2807 void main() {
2808     vColor = aColor;
2809     gl_Position = position + vec4(aOffset, 0.0, 0.0);
2810 })";
2811 
2812     ANGLE_GL_PROGRAM(renderProgram1, kVertexShader1, kFragmentShader);
2813 
2814     std::array<GLfloat, 8> offsets = {
2815         -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0,
2816     };
2817     GLBuffer offsetBuffer;
2818     glBindBuffer(GL_ARRAY_BUFFER, offsetBuffer);
2819     glBufferData(GL_ARRAY_BUFFER, offsets.size() * sizeof(GLfloat), offsets.data(), GL_STATIC_DRAW);
2820 
2821     std::array<GLfloat, 16> colors0 = {
2822         1.0, 0.0, 0.0, 1.0,  // Red
2823         0.0, 1.0, 0.0, 1.0,  // Green
2824         0.0, 0.0, 1.0, 1.0,  // Blue
2825         1.0, 1.0, 0.0, 1.0,  // Yellow
2826     };
2827     std::array<GLfloat, 16> colors1 = {
2828         1.0, 1.0, 0.0, 1.0,  // Yellow
2829         0.0, 0.0, 1.0, 1.0,  // Blue
2830         0.0, 1.0, 0.0, 1.0,  // Green
2831         1.0, 0.0, 0.0, 1.0,  // Red
2832     };
2833     GLBuffer colorBuffers[2];
2834     glBindBuffer(GL_ARRAY_BUFFER, colorBuffers[0]);
2835     glBufferData(GL_ARRAY_BUFFER, colors0.size() * sizeof(GLfloat), colors0.data(), GL_STATIC_DRAW);
2836     glBindBuffer(GL_ARRAY_BUFFER, colorBuffers[1]);
2837     glBufferData(GL_ARRAY_BUFFER, colors1.size() * sizeof(GLfloat), colors1.data(), GL_STATIC_DRAW);
2838 
2839     std::array<GLfloat, 16> positions = {1.0, 1.0, -1.0, 1.0,  -1.0, -1.0,
2840                                          1.0, 1.0, -1.0, -1.0, 1.0,  -1.0};
2841     GLBuffer positionBuffer;
2842     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
2843     glBufferData(GL_ARRAY_BUFFER, positions.size() * sizeof(GLfloat), positions.data(),
2844                  GL_STATIC_DRAW);
2845 
2846     const int kInstanceCount = 4;
2847     GLVertexArray vao[2];
2848     for (size_t i = 0u; i < 2u; ++i)
2849     {
2850         glBindVertexArray(vao[i]);
2851 
2852         glBindBuffer(GL_ARRAY_BUFFER, offsetBuffer);
2853         glEnableVertexAttribArray(2);
2854         glVertexAttribPointer(2, 2, GL_FLOAT, false, 0, 0);
2855         glVertexAttribDivisor(2, 1);
2856 
2857         glBindBuffer(GL_ARRAY_BUFFER, colorBuffers[i]);
2858         glEnableVertexAttribArray(3);
2859         glVertexAttribPointer(3, 4, GL_FLOAT, false, 0, 0);
2860         glVertexAttribDivisor(3, 1);
2861 
2862         glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
2863         glEnableVertexAttribArray(i);
2864         glVertexAttribPointer(i, 2, GL_FLOAT, false, 0, 0);
2865     }
2866 
2867     glClear(GL_COLOR_BUFFER_BIT);
2868 
2869     for (int i = 0; i < 3; i++)
2870     {
2871         glUseProgram(renderProgram);
2872         glBindVertexArray(vao[0]);
2873         glDrawArraysInstanced(GL_TRIANGLES, 0, 6, kInstanceCount);
2874 
2875         EXPECT_GL_NO_ERROR();
2876         EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 2, GLColor::red) << i;
2877         EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::green) << i;
2878         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue) << i;
2879         EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::yellow) << i;
2880 
2881         glBindVertexArray(vao[1]);
2882         glUseProgram(computeProgram);
2883         glDispatchCompute(1, 1, 1);
2884 
2885         glUseProgram(renderProgram1);
2886         glBindVertexArray(vao[1]);
2887         glDrawArraysInstanced(GL_TRIANGLES, 0, 6, kInstanceCount);
2888 
2889         EXPECT_GL_NO_ERROR();
2890         EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 2, GLColor::yellow) << i;
2891         EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::blue) << i;
2892         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green) << i;
2893         EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::red) << i;
2894     }
2895     ASSERT_GL_NO_ERROR();
2896 }
2897 
TEST_P(VertexAttributeTestES31,UseComputeShaderToUpdateVertexBuffer)2898 TEST_P(VertexAttributeTestES31, UseComputeShaderToUpdateVertexBuffer)
2899 {
2900     initTest();
2901     constexpr char kComputeShader[] =
2902         R"(#version 310 es
2903 layout(local_size_x=24) in;
2904 layout(std430, binding = 0) buffer buf {
2905     uint outData[24];
2906 };
2907 void main()
2908 {
2909     outData[gl_LocalInvocationIndex] = gl_LocalInvocationIndex;
2910 })";
2911 
2912     ANGLE_GL_COMPUTE_PROGRAM(computeProgram, kComputeShader);
2913     glUseProgram(mProgram);
2914 
2915     GLuint mid                                 = std::numeric_limits<GLuint>::max() >> 1;
2916     GLuint hi                                  = std::numeric_limits<GLuint>::max();
2917     std::array<GLuint, kVertexCount> inputData = {
2918         {0, 1, 2, 3, 254, 255, 256, mid - 1, mid, mid + 1, hi - 2, hi - 1, hi}};
2919     std::array<GLfloat, kVertexCount> expectedData;
2920     for (size_t i = 0; i < kVertexCount; i++)
2921     {
2922         expectedData[i] = Normalize(inputData[i]);
2923     }
2924 
2925     // Normalized unsigned int attribute will be classified as translated static attribute.
2926     TestData data(GL_UNSIGNED_INT, GL_TRUE, Source::BUFFER, inputData.data(), expectedData.data());
2927     GLint typeSize   = 4;
2928     GLsizei dataSize = kVertexCount * TypeStride(data.type);
2929     GLBuffer testBuffer;
2930     glBindBuffer(GL_ARRAY_BUFFER, testBuffer);
2931     glBufferData(GL_ARRAY_BUFFER, dataSize, data.inputData, GL_STATIC_DRAW);
2932     glVertexAttribPointer(mTestAttrib, typeSize, data.type, data.normalized, 0,
2933                           reinterpret_cast<void *>(data.bufferOffset));
2934     glEnableVertexAttribArray(mTestAttrib);
2935 
2936     glBindBuffer(GL_ARRAY_BUFFER, mExpectedBuffer);
2937     glBufferData(GL_ARRAY_BUFFER, dataSize, data.expectedData, GL_STATIC_DRAW);
2938     glVertexAttribPointer(mExpectedAttrib, typeSize, GL_FLOAT, GL_FALSE, 0, nullptr);
2939 
2940     // Draw twice to make sure that all static attributes dirty bits are synced.
2941     glDrawArrays(GL_TRIANGLES, 0, 6);
2942     glDrawArrays(GL_TRIANGLES, 0, 6);
2943     checkPixels();
2944 
2945     // Modify the testBuffer using a raw buffer
2946     glUseProgram(computeProgram);
2947     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, testBuffer);
2948     glDispatchCompute(1, 1, 1);
2949     glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
2950 
2951     // Draw again to verify that testBuffer has been changed.
2952     glUseProgram(mProgram);
2953     glDrawArrays(GL_TRIANGLES, 0, 6);
2954     EXPECT_GL_NO_ERROR();
2955     checkPixelsUnEqual();
2956 }
2957 
TEST_P(VertexAttributeTestES31,UsePpoComputeShaderToUpdateVertexBuffer)2958 TEST_P(VertexAttributeTestES31, UsePpoComputeShaderToUpdateVertexBuffer)
2959 {
2960     // PPOs are only supported in the Vulkan backend
2961     ANGLE_SKIP_TEST_IF(!isVulkanRenderer());
2962 
2963     initTest();
2964     constexpr char kComputeShader[] =
2965         R"(#version 310 es
2966 layout(local_size_x=24) in;
2967 layout(std430, binding = 0) buffer buf {
2968     uint outData[24];
2969 };
2970 void main()
2971 {
2972     outData[gl_LocalInvocationIndex] = gl_LocalInvocationIndex;
2973 })";
2974 
2975     glUseProgram(mProgram);
2976 
2977     GLuint mid                                 = std::numeric_limits<GLuint>::max() >> 1;
2978     GLuint hi                                  = std::numeric_limits<GLuint>::max();
2979     std::array<GLuint, kVertexCount> inputData = {
2980         {0, 1, 2, 3, 254, 255, 256, mid - 1, mid, mid + 1, hi - 2, hi - 1, hi}};
2981     std::array<GLfloat, kVertexCount> expectedData;
2982     for (size_t i = 0; i < kVertexCount; i++)
2983     {
2984         expectedData[i] = Normalize(inputData[i]);
2985     }
2986 
2987     // Normalized unsigned int attribute will be classified as translated static attribute.
2988     TestData data(GL_UNSIGNED_INT, GL_TRUE, Source::BUFFER, inputData.data(), expectedData.data());
2989     GLint typeSize   = 4;
2990     GLsizei dataSize = kVertexCount * TypeStride(data.type);
2991     GLBuffer testBuffer;
2992     glBindBuffer(GL_ARRAY_BUFFER, testBuffer);
2993     glBufferData(GL_ARRAY_BUFFER, dataSize, data.inputData, GL_STATIC_DRAW);
2994     glVertexAttribPointer(mTestAttrib, typeSize, data.type, data.normalized, 0,
2995                           reinterpret_cast<void *>(data.bufferOffset));
2996     glEnableVertexAttribArray(mTestAttrib);
2997 
2998     glBindBuffer(GL_ARRAY_BUFFER, mExpectedBuffer);
2999     glBufferData(GL_ARRAY_BUFFER, dataSize, data.expectedData, GL_STATIC_DRAW);
3000     glVertexAttribPointer(mExpectedAttrib, typeSize, GL_FLOAT, GL_FALSE, 0, nullptr);
3001 
3002     // Draw twice to make sure that all static attributes dirty bits are synced.
3003     glDrawArrays(GL_TRIANGLES, 0, 6);
3004     glDrawArrays(GL_TRIANGLES, 0, 6);
3005     checkPixels();
3006 
3007     // Modify the testBuffer using a raw buffer
3008     GLProgramPipeline pipeline;
3009     ANGLE_GL_COMPUTE_PROGRAM(computeProgram, kComputeShader);
3010     glProgramParameteri(computeProgram, GL_PROGRAM_SEPARABLE, GL_TRUE);
3011     glUseProgramStages(pipeline, GL_COMPUTE_SHADER_BIT, computeProgram);
3012     EXPECT_GL_NO_ERROR();
3013     glBindProgramPipeline(pipeline);
3014     EXPECT_GL_NO_ERROR();
3015     glUseProgram(0);
3016 
3017     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, testBuffer);
3018     glDispatchCompute(1, 1, 1);
3019     glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
3020 
3021     // Draw again to verify that testBuffer has been changed.
3022     glUseProgram(mProgram);
3023     glDrawArrays(GL_TRIANGLES, 0, 6);
3024     EXPECT_GL_NO_ERROR();
3025     checkPixelsUnEqual();
3026 }
3027 
TEST_P(VertexAttributeTestES31,UseComputeShaderToUpdateVertexBufferSamePpo)3028 TEST_P(VertexAttributeTestES31, UseComputeShaderToUpdateVertexBufferSamePpo)
3029 {
3030     // PPOs are only supported in the Vulkan backend
3031     ANGLE_SKIP_TEST_IF(!isVulkanRenderer());
3032 
3033     initTest();
3034     constexpr char kComputeShader[] =
3035         R"(#version 310 es
3036 layout(local_size_x=24) in;
3037 layout(std430, binding = 0) buffer buf {
3038     uint outData[24];
3039 };
3040 void main()
3041 {
3042     outData[gl_LocalInvocationIndex] = gl_LocalInvocationIndex;
3043 })";
3044 
3045     // Mark the program separable and re-link it so it can be bound to the PPO.
3046     glProgramParameteri(mProgram, GL_PROGRAM_SEPARABLE, GL_TRUE);
3047     glLinkProgram(mProgram);
3048     mProgram = CheckLinkStatusAndReturnProgram(mProgram, true);
3049 
3050     GLProgramPipeline pipeline;
3051     EXPECT_GL_NO_ERROR();
3052     glBindProgramPipeline(pipeline);
3053     glUseProgramStages(pipeline, GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, mProgram);
3054     EXPECT_GL_NO_ERROR();
3055     glUseProgram(0);
3056 
3057     GLuint mid                                 = std::numeric_limits<GLuint>::max() >> 1;
3058     GLuint hi                                  = std::numeric_limits<GLuint>::max();
3059     std::array<GLuint, kVertexCount> inputData = {
3060         {0, 1, 2, 3, 254, 255, 256, mid - 1, mid, mid + 1, hi - 2, hi - 1, hi}};
3061     std::array<GLfloat, kVertexCount> expectedData;
3062     for (size_t i = 0; i < kVertexCount; i++)
3063     {
3064         expectedData[i] = Normalize(inputData[i]);
3065     }
3066 
3067     // Normalized unsigned int attribute will be classified as translated static attribute.
3068     TestData data(GL_UNSIGNED_INT, GL_TRUE, Source::BUFFER, inputData.data(), expectedData.data());
3069     GLint typeSize   = 4;
3070     GLsizei dataSize = kVertexCount * TypeStride(data.type);
3071     GLBuffer testBuffer;
3072     glBindBuffer(GL_ARRAY_BUFFER, testBuffer);
3073     glBufferData(GL_ARRAY_BUFFER, dataSize, data.inputData, GL_STATIC_DRAW);
3074     glVertexAttribPointer(mTestAttrib, typeSize, data.type, data.normalized, 0,
3075                           reinterpret_cast<void *>(data.bufferOffset));
3076     glEnableVertexAttribArray(mTestAttrib);
3077 
3078     glBindBuffer(GL_ARRAY_BUFFER, mExpectedBuffer);
3079     glBufferData(GL_ARRAY_BUFFER, dataSize, data.expectedData, GL_STATIC_DRAW);
3080     glVertexAttribPointer(mExpectedAttrib, typeSize, GL_FLOAT, GL_FALSE, 0, nullptr);
3081 
3082     // Draw twice to make sure that all static attributes dirty bits are synced.
3083     glDrawArrays(GL_TRIANGLES, 0, 6);
3084     glDrawArrays(GL_TRIANGLES, 0, 6);
3085     checkPixels();
3086 
3087     // Modify the testBuffer using a raw buffer
3088     ANGLE_GL_COMPUTE_PROGRAM(computeProgram, kComputeShader);
3089     glProgramParameteri(computeProgram, GL_PROGRAM_SEPARABLE, GL_TRUE);
3090     glUseProgramStages(pipeline, GL_COMPUTE_SHADER_BIT, computeProgram);
3091     EXPECT_GL_NO_ERROR();
3092 
3093     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, testBuffer);
3094     glDispatchCompute(1, 1, 1);
3095     glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
3096 
3097     // Draw again to verify that testBuffer has been changed.
3098     glUseProgram(mProgram);
3099     glDrawArrays(GL_TRIANGLES, 0, 6);
3100     EXPECT_GL_NO_ERROR();
3101     checkPixelsUnEqual();
3102 }
3103 
3104 // Verify that using VertexAttribBinding after VertexAttribPointer won't mess up the draw.
TEST_P(VertexAttributeTestES31,ChangeAttribBindingAfterVertexAttribPointer)3105 TEST_P(VertexAttributeTestES31, ChangeAttribBindingAfterVertexAttribPointer)
3106 {
3107     initTest();
3108 
3109     constexpr GLint kInputStride = 2;
3110     constexpr GLint kFloatOffset = 10;
3111     std::array<GLfloat, kVertexCount + kFloatOffset> inputData1;
3112     std::array<GLfloat, kVertexCount * kInputStride> inputData2;
3113     for (size_t count = 0; count < kVertexCount; ++count)
3114     {
3115         inputData1[kFloatOffset + count] = static_cast<GLfloat>(count);
3116         inputData2[count * kInputStride] = static_cast<GLfloat>(count);
3117     }
3118 
3119     GLBuffer mBuffer1;
3120     glBindBuffer(GL_ARRAY_BUFFER, mBuffer1);
3121     glBufferData(GL_ARRAY_BUFFER, inputData1.size() * kFloatStride, inputData1.data(),
3122                  GL_STATIC_DRAW);
3123     // Update the format indexed mTestAttrib and the binding indexed mTestAttrib by
3124     // VertexAttribPointer.
3125     const GLintptr kOffset = static_cast<GLintptr>(kFloatStride * kFloatOffset);
3126     glVertexAttribPointer(mTestAttrib, 1, GL_FLOAT, GL_FALSE, 0,
3127                           reinterpret_cast<const GLvoid *>(kOffset));
3128     glEnableVertexAttribArray(mTestAttrib);
3129 
3130     constexpr GLint kTestBinding = 10;
3131     ASSERT_NE(mTestAttrib, kTestBinding);
3132 
3133     GLBuffer mBuffer2;
3134     glBindBuffer(GL_ARRAY_BUFFER, mBuffer2);
3135     glBufferData(GL_ARRAY_BUFFER, inputData2.size() * kFloatStride, inputData2.data(),
3136                  GL_STATIC_DRAW);
3137     glBindVertexBuffer(kTestBinding, mBuffer2, 0, kFloatStride * kInputStride);
3138 
3139     // The attribute indexed mTestAttrib is using the binding indexed kTestBinding in the first
3140     // draw.
3141     glVertexAttribBinding(mTestAttrib, kTestBinding);
3142     glDrawArrays(GL_TRIANGLES, 0, 6);
3143     checkPixels();
3144     EXPECT_GL_NO_ERROR();
3145 
3146     // The attribute indexed mTestAttrib is using the binding indexed mTestAttrib which should be
3147     // set after the call VertexAttribPointer before the first draw.
3148     glVertexAttribBinding(mTestAttrib, mTestAttrib);
3149     glDrawArrays(GL_TRIANGLES, 0, 6);
3150     checkPixels();
3151     EXPECT_GL_NO_ERROR();
3152 }
3153 
3154 // Verify that using VertexAttribFormat after VertexAttribPointer won't mess up the draw.
TEST_P(VertexAttributeTestES31,ChangeAttribFormatAfterVertexAttribPointer)3155 TEST_P(VertexAttributeTestES31, ChangeAttribFormatAfterVertexAttribPointer)
3156 {
3157     initTest();
3158 
3159     constexpr GLuint kFloatOffset = 10;
3160     std::array<GLfloat, kVertexCount + kFloatOffset> inputData;
3161     for (size_t count = 0; count < kVertexCount; ++count)
3162     {
3163         inputData[kFloatOffset + count] = static_cast<GLfloat>(count);
3164     }
3165 
3166     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
3167     glBufferData(GL_ARRAY_BUFFER, inputData.size() * kFloatStride, inputData.data(),
3168                  GL_STATIC_DRAW);
3169 
3170     // Call VertexAttribPointer on mTestAttrib. Now the relativeOffset of mTestAttrib should be 0.
3171     const GLuint kOffset = static_cast<GLuint>(kFloatStride * kFloatOffset);
3172     glVertexAttribPointer(mTestAttrib, 1, GL_FLOAT, GL_FALSE, 0, 0);
3173     glEnableVertexAttribArray(mTestAttrib);
3174 
3175     // Call VertexAttribFormat on mTestAttrib to modify the relativeOffset to kOffset.
3176     glVertexAttribFormat(mTestAttrib, 1, GL_FLOAT, GL_FALSE, kOffset);
3177 
3178     glDrawArrays(GL_TRIANGLES, 0, 6);
3179     checkPixels();
3180     EXPECT_GL_NO_ERROR();
3181 }
3182 
3183 // Verify that only updating a binding without updating the bound format won't mess up this draw.
TEST_P(VertexAttributeTestES31,OnlyUpdateBindingByBindVertexBuffer)3184 TEST_P(VertexAttributeTestES31, OnlyUpdateBindingByBindVertexBuffer)
3185 {
3186     // Default binding index for test
3187     constexpr GLint kTestBinding = 10;
3188     initOnlyUpdateBindingTest(kTestBinding);
3189 
3190     constexpr GLuint kTestFloatOffset2                               = kVertexCount * 2;
3191     std::array<GLfloat, kVertexCount> expectedData2                  = {};
3192     std::array<GLfloat, kTestFloatOffset2 + kVertexCount> inputData2 = {};
3193     for (size_t count = 0; count < kVertexCount; ++count)
3194     {
3195         GLfloat value2                        = static_cast<GLfloat>(count) * 2;
3196         expectedData2[count]                  = value2;
3197         inputData2[count + kTestFloatOffset2] = value2;
3198     }
3199 
3200     // Set another set of data for mExpectedAttrib.
3201     GLBuffer expectedBuffer2;
3202     glBindBuffer(GL_ARRAY_BUFFER, expectedBuffer2);
3203     glBufferData(GL_ARRAY_BUFFER, expectedData2.size() * kFloatStride, expectedData2.data(),
3204                  GL_STATIC_DRAW);
3205     glVertexAttribPointer(mExpectedAttrib, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
3206 
3207     GLBuffer testBuffer2;
3208     glBindBuffer(GL_ARRAY_BUFFER, testBuffer2);
3209     glBufferData(GL_ARRAY_BUFFER, inputData2.size() * kFloatStride, inputData2.data(),
3210                  GL_STATIC_DRAW);
3211 
3212     // Only update the binding kTestBinding in the second draw by BindVertexBuffer.
3213     glBindVertexBuffer(kTestBinding, testBuffer2, kTestFloatOffset2 * kFloatStride, kFloatStride);
3214 
3215     glDrawArrays(GL_TRIANGLES, 0, 6);
3216     checkPixels();
3217     EXPECT_GL_NO_ERROR();
3218 }
3219 
3220 // Verify that only updating a binding without updating the bound format won't mess up this draw.
TEST_P(VertexAttributeTestES31,OnlyUpdateBindingByVertexAttribPointer)3221 TEST_P(VertexAttributeTestES31, OnlyUpdateBindingByVertexAttribPointer)
3222 {
3223     // Default binding index for test
3224     constexpr GLint kTestBinding = 10;
3225     initOnlyUpdateBindingTest(kTestBinding);
3226 
3227     constexpr GLuint kTestFloatOffset2                               = kVertexCount * 3;
3228     std::array<GLfloat, kVertexCount> expectedData2                  = {};
3229     std::array<GLfloat, kTestFloatOffset2 + kVertexCount> inputData2 = {};
3230     for (size_t count = 0; count < kVertexCount; ++count)
3231     {
3232         GLfloat value2                        = static_cast<GLfloat>(count) * 3;
3233         expectedData2[count]                  = value2;
3234         inputData2[count + kTestFloatOffset2] = value2;
3235     }
3236 
3237     // Set another set of data for mExpectedAttrib.
3238     GLBuffer expectedBuffer2;
3239     glBindBuffer(GL_ARRAY_BUFFER, expectedBuffer2);
3240     glBufferData(GL_ARRAY_BUFFER, expectedData2.size() * kFloatStride, expectedData2.data(),
3241                  GL_STATIC_DRAW);
3242     glVertexAttribPointer(mExpectedAttrib, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
3243 
3244     GLBuffer testBuffer2;
3245     glBindBuffer(GL_ARRAY_BUFFER, testBuffer2);
3246     glBufferData(GL_ARRAY_BUFFER, inputData2.size() * kFloatStride, inputData2.data(),
3247                  GL_STATIC_DRAW);
3248 
3249     // Only update the binding kTestBinding in the second draw by VertexAttribPointer.
3250     glVertexAttribPointer(
3251         kTestBinding, 1, GL_FLOAT, GL_FALSE, 0,
3252         reinterpret_cast<const void *>(static_cast<uintptr_t>(kTestFloatOffset2 * kFloatStride)));
3253 
3254     glDrawArrays(GL_TRIANGLES, 0, 6);
3255     checkPixels();
3256     EXPECT_GL_NO_ERROR();
3257 }
3258 
3259 class VertexAttributeCachingTest : public VertexAttributeTest
3260 {
3261   protected:
VertexAttributeCachingTest()3262     VertexAttributeCachingTest() {}
3263 
3264     void testSetUp() override;
3265 
3266     template <typename DestT>
3267     static std::vector<GLfloat> GetExpectedData(const std::vector<GLubyte> &srcData,
3268                                                 GLenum attribType,
3269                                                 GLboolean normalized);
3270 
initDoubleAttribProgram()3271     void initDoubleAttribProgram()
3272     {
3273         constexpr char kVS[] =
3274             "attribute mediump vec4 position;\n"
3275             "attribute mediump vec4 test;\n"
3276             "attribute mediump vec4 expected;\n"
3277             "attribute mediump vec4 test2;\n"
3278             "attribute mediump vec4 expected2;\n"
3279             "varying mediump vec4 color;\n"
3280             "void main(void)\n"
3281             "{\n"
3282             "    gl_Position = position;\n"
3283             "    vec4 threshold = max(abs(expected) * 0.01, 1.0 / 64.0);\n"
3284             "    color = vec4(lessThanEqual(abs(test - expected), threshold));\n"
3285             "    vec4 threshold2 = max(abs(expected2) * 0.01, 1.0 / 64.0);\n"
3286             "    color += vec4(lessThanEqual(abs(test2 - expected2), threshold2));\n"
3287             "}\n";
3288 
3289         constexpr char kFS[] =
3290             "varying mediump vec4 color;\n"
3291             "void main(void)\n"
3292             "{\n"
3293             "    gl_FragColor = color;\n"
3294             "}\n";
3295 
3296         mProgram = CompileProgram(kVS, kFS);
3297         ASSERT_NE(0u, mProgram);
3298 
3299         mTestAttrib = glGetAttribLocation(mProgram, "test");
3300         ASSERT_NE(-1, mTestAttrib);
3301         mExpectedAttrib = glGetAttribLocation(mProgram, "expected");
3302         ASSERT_NE(-1, mExpectedAttrib);
3303 
3304         glUseProgram(mProgram);
3305     }
3306 
3307     struct AttribData
3308     {
3309         AttribData(GLenum typeIn, GLint sizeIn, GLboolean normalizedIn, GLsizei strideIn);
3310 
3311         GLenum type;
3312         GLint size;
3313         GLboolean normalized;
3314         GLsizei stride;
3315     };
3316 
3317     std::vector<AttribData> mTestData;
3318     std::map<GLenum, std::vector<GLfloat>> mExpectedData;
3319     std::map<GLenum, std::vector<GLfloat>> mNormExpectedData;
3320 };
3321 
AttribData(GLenum typeIn,GLint sizeIn,GLboolean normalizedIn,GLsizei strideIn)3322 VertexAttributeCachingTest::AttribData::AttribData(GLenum typeIn,
3323                                                    GLint sizeIn,
3324                                                    GLboolean normalizedIn,
3325                                                    GLsizei strideIn)
3326     : type(typeIn), size(sizeIn), normalized(normalizedIn), stride(strideIn)
3327 {}
3328 
3329 // static
3330 template <typename DestT>
GetExpectedData(const std::vector<GLubyte> & srcData,GLenum attribType,GLboolean normalized)3331 std::vector<GLfloat> VertexAttributeCachingTest::GetExpectedData(
3332     const std::vector<GLubyte> &srcData,
3333     GLenum attribType,
3334     GLboolean normalized)
3335 {
3336     std::vector<GLfloat> expectedData;
3337 
3338     const DestT *typedSrcPtr = reinterpret_cast<const DestT *>(srcData.data());
3339     size_t iterations        = srcData.size() / TypeStride(attribType);
3340 
3341     if (normalized)
3342     {
3343         for (size_t index = 0; index < iterations; ++index)
3344         {
3345             expectedData.push_back(Normalize(typedSrcPtr[index]));
3346         }
3347     }
3348     else
3349     {
3350         for (size_t index = 0; index < iterations; ++index)
3351         {
3352             expectedData.push_back(static_cast<GLfloat>(typedSrcPtr[index]));
3353         }
3354     }
3355 
3356     return expectedData;
3357 }
3358 
testSetUp()3359 void VertexAttributeCachingTest::testSetUp()
3360 {
3361     VertexAttributeTest::testSetUp();
3362 
3363     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
3364 
3365     std::vector<GLubyte> srcData;
3366     for (size_t count = 0; count < 4; ++count)
3367     {
3368         for (GLubyte i = 0; i < std::numeric_limits<GLubyte>::max(); ++i)
3369         {
3370             srcData.push_back(i);
3371         }
3372     }
3373 
3374     glBufferData(GL_ARRAY_BUFFER, srcData.size(), srcData.data(), GL_STATIC_DRAW);
3375 
3376     GLint viewportSize[4];
3377     glGetIntegerv(GL_VIEWPORT, viewportSize);
3378 
3379     std::vector<GLenum> attribTypes;
3380     attribTypes.push_back(GL_BYTE);
3381     attribTypes.push_back(GL_UNSIGNED_BYTE);
3382     attribTypes.push_back(GL_SHORT);
3383     attribTypes.push_back(GL_UNSIGNED_SHORT);
3384 
3385     if (getClientMajorVersion() >= 3)
3386     {
3387         attribTypes.push_back(GL_INT);
3388         attribTypes.push_back(GL_UNSIGNED_INT);
3389     }
3390 
3391     constexpr GLint kMaxSize     = 4;
3392     constexpr GLsizei kMaxStride = 4;
3393 
3394     for (GLenum attribType : attribTypes)
3395     {
3396         for (GLint attribSize = 1; attribSize <= kMaxSize; ++attribSize)
3397         {
3398             for (GLsizei stride = 1; stride <= kMaxStride; ++stride)
3399             {
3400                 mTestData.push_back(AttribData(attribType, attribSize, GL_FALSE, stride));
3401                 if (attribType != GL_FLOAT)
3402                 {
3403                     mTestData.push_back(AttribData(attribType, attribSize, GL_TRUE, stride));
3404                 }
3405             }
3406         }
3407     }
3408 
3409     mExpectedData[GL_BYTE]          = GetExpectedData<GLbyte>(srcData, GL_BYTE, GL_FALSE);
3410     mExpectedData[GL_UNSIGNED_BYTE] = GetExpectedData<GLubyte>(srcData, GL_UNSIGNED_BYTE, GL_FALSE);
3411     mExpectedData[GL_SHORT]         = GetExpectedData<GLshort>(srcData, GL_SHORT, GL_FALSE);
3412     mExpectedData[GL_UNSIGNED_SHORT] =
3413         GetExpectedData<GLushort>(srcData, GL_UNSIGNED_SHORT, GL_FALSE);
3414     mExpectedData[GL_INT]          = GetExpectedData<GLint>(srcData, GL_INT, GL_FALSE);
3415     mExpectedData[GL_UNSIGNED_INT] = GetExpectedData<GLuint>(srcData, GL_UNSIGNED_INT, GL_FALSE);
3416 
3417     mNormExpectedData[GL_BYTE] = GetExpectedData<GLbyte>(srcData, GL_BYTE, GL_TRUE);
3418     mNormExpectedData[GL_UNSIGNED_BYTE] =
3419         GetExpectedData<GLubyte>(srcData, GL_UNSIGNED_BYTE, GL_TRUE);
3420     mNormExpectedData[GL_SHORT] = GetExpectedData<GLshort>(srcData, GL_SHORT, GL_TRUE);
3421     mNormExpectedData[GL_UNSIGNED_SHORT] =
3422         GetExpectedData<GLushort>(srcData, GL_UNSIGNED_SHORT, GL_TRUE);
3423     mNormExpectedData[GL_INT]          = GetExpectedData<GLint>(srcData, GL_INT, GL_TRUE);
3424     mNormExpectedData[GL_UNSIGNED_INT] = GetExpectedData<GLuint>(srcData, GL_UNSIGNED_INT, GL_TRUE);
3425 }
3426 
3427 // In D3D11, we must sometimes translate buffer data into static attribute caches. We also use a
3428 // cache management scheme which garbage collects old attributes after we start using too much
3429 // cache data. This test tries to make as many attribute caches from a single buffer as possible
3430 // to stress-test the caching code.
TEST_P(VertexAttributeCachingTest,BufferMulticaching)3431 TEST_P(VertexAttributeCachingTest, BufferMulticaching)
3432 {
3433     ANGLE_SKIP_TEST_IF(IsAMD() && IsDesktopOpenGL());
3434 
3435     initBasicProgram();
3436 
3437     glEnableVertexAttribArray(mTestAttrib);
3438     glEnableVertexAttribArray(mExpectedAttrib);
3439 
3440     ASSERT_GL_NO_ERROR();
3441 
3442     for (const AttribData &data : mTestData)
3443     {
3444         const auto &expected =
3445             (data.normalized) ? mNormExpectedData[data.type] : mExpectedData[data.type];
3446 
3447         GLsizei baseStride = static_cast<GLsizei>(data.size) * data.stride;
3448         GLsizei stride     = TypeStride(data.type) * baseStride;
3449 
3450         glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
3451         glVertexAttribPointer(mTestAttrib, data.size, data.type, data.normalized, stride, nullptr);
3452         glBindBuffer(GL_ARRAY_BUFFER, 0);
3453         glVertexAttribPointer(mExpectedAttrib, data.size, GL_FLOAT, GL_FALSE,
3454                               sizeof(GLfloat) * baseStride, expected.data());
3455         drawQuad(mProgram, "position", 0.5f);
3456         ASSERT_GL_NO_ERROR();
3457         EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::white);
3458     }
3459 }
3460 
3461 // With D3D11 dirty bits for VertxArray11, we can leave vertex state unchanged if there aren't any
3462 // GL calls that affect it. This test targets leaving one vertex attribute unchanged between draw
3463 // calls while changing another vertex attribute enough that it clears the static buffer cache
3464 // after enough iterations. It validates the unchanged attributes don't get deleted incidentally.
TEST_P(VertexAttributeCachingTest,BufferMulticachingWithOneUnchangedAttrib)3465 TEST_P(VertexAttributeCachingTest, BufferMulticachingWithOneUnchangedAttrib)
3466 {
3467     ANGLE_SKIP_TEST_IF(IsAMD() && IsDesktopOpenGL());
3468 
3469     initDoubleAttribProgram();
3470 
3471     GLint testAttrib2Location = glGetAttribLocation(mProgram, "test2");
3472     ASSERT_NE(-1, testAttrib2Location);
3473     GLint expectedAttrib2Location = glGetAttribLocation(mProgram, "expected2");
3474     ASSERT_NE(-1, expectedAttrib2Location);
3475 
3476     glEnableVertexAttribArray(mTestAttrib);
3477     glEnableVertexAttribArray(mExpectedAttrib);
3478     glEnableVertexAttribArray(testAttrib2Location);
3479     glEnableVertexAttribArray(expectedAttrib2Location);
3480 
3481     ASSERT_GL_NO_ERROR();
3482 
3483     // Use an attribute that we know must be converted. This is a bit sensitive.
3484     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
3485     glVertexAttribPointer(testAttrib2Location, 3, GL_UNSIGNED_SHORT, GL_FALSE, 6, nullptr);
3486     glBindBuffer(GL_ARRAY_BUFFER, 0);
3487     glVertexAttribPointer(expectedAttrib2Location, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3,
3488                           mExpectedData[GL_UNSIGNED_SHORT].data());
3489 
3490     for (const auto &data : mTestData)
3491     {
3492         const auto &expected =
3493             (data.normalized) ? mNormExpectedData[data.type] : mExpectedData[data.type];
3494 
3495         GLsizei baseStride = static_cast<GLsizei>(data.size) * data.stride;
3496         GLsizei stride     = TypeStride(data.type) * baseStride;
3497 
3498         glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
3499         glVertexAttribPointer(mTestAttrib, data.size, data.type, data.normalized, stride, nullptr);
3500         glBindBuffer(GL_ARRAY_BUFFER, 0);
3501         glVertexAttribPointer(mExpectedAttrib, data.size, GL_FLOAT, GL_FALSE,
3502                               sizeof(GLfloat) * baseStride, expected.data());
3503         drawQuad(mProgram, "position", 0.5f);
3504 
3505         ASSERT_GL_NO_ERROR();
3506         EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 255, 255, 255);
3507     }
3508 }
3509 
3510 // Test that if there are gaps in the attribute indices, the attributes have their correct values.
TEST_P(VertexAttributeTest,UnusedVertexAttribWorks)3511 TEST_P(VertexAttributeTest, UnusedVertexAttribWorks)
3512 {
3513     constexpr char kVertexShader[] = R"(attribute vec2 position;
3514 attribute float actualValue;
3515 uniform float expectedValue;
3516 varying float result;
3517 void main()
3518 {
3519     result = (actualValue == expectedValue) ? 1.0 : 0.0;
3520     gl_Position = vec4(position, 0, 1);
3521 })";
3522 
3523     constexpr char kFragmentShader[] = R"(varying mediump float result;
3524 void main()
3525 {
3526     gl_FragColor = result > 0.0 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
3527 })";
3528 
3529     ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
3530 
3531     // Force a gap in attributes by using location 0 and 3
3532     GLint positionLocation = 0;
3533     glBindAttribLocation(program, positionLocation, "position");
3534 
3535     GLint attribLoc = 3;
3536     glBindAttribLocation(program, attribLoc, "actualValue");
3537 
3538     // Re-link the program to update the attribute locations
3539     glLinkProgram(program);
3540     ASSERT_TRUE(CheckLinkStatusAndReturnProgram(program, true));
3541 
3542     glUseProgram(program);
3543 
3544     GLint uniLoc = glGetUniformLocation(program, "expectedValue");
3545     ASSERT_NE(-1, uniLoc);
3546 
3547     glVertexAttribPointer(attribLoc, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
3548 
3549     ASSERT_NE(-1, positionLocation);
3550     setupQuadVertexBuffer(0.5f, 1.0f);
3551     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
3552     glEnableVertexAttribArray(positionLocation);
3553 
3554     std::array<GLfloat, 4> testValues = {{1, 2, 3, 4}};
3555     for (GLfloat testValue : testValues)
3556     {
3557         glUniform1f(uniLoc, testValue);
3558         glVertexAttrib1f(attribLoc, testValue);
3559         glDrawArrays(GL_TRIANGLES, 0, 6);
3560         ASSERT_GL_NO_ERROR();
3561         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3562     }
3563 }
3564 
3565 // Tests that repeatedly updating a disabled vertex attribute works as expected.
3566 // This covers an ANGLE bug where dirty bits for current values were ignoring repeated updates.
TEST_P(VertexAttributeTest,DisabledAttribUpdates)3567 TEST_P(VertexAttributeTest, DisabledAttribUpdates)
3568 {
3569     constexpr char kVertexShader[] = R"(attribute vec2 position;
3570 attribute float actualValue;
3571 uniform float expectedValue;
3572 varying float result;
3573 void main()
3574 {
3575     result = (actualValue == expectedValue) ? 1.0 : 0.0;
3576     gl_Position = vec4(position, 0, 1);
3577 })";
3578 
3579     constexpr char kFragmentShader[] = R"(varying mediump float result;
3580 void main()
3581 {
3582     gl_FragColor = result > 0.0 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
3583 })";
3584 
3585     ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
3586 
3587     glUseProgram(program);
3588     GLint attribLoc = glGetAttribLocation(program, "actualValue");
3589     ASSERT_NE(-1, attribLoc);
3590 
3591     GLint uniLoc = glGetUniformLocation(program, "expectedValue");
3592     ASSERT_NE(-1, uniLoc);
3593 
3594     glVertexAttribPointer(attribLoc, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
3595 
3596     GLint positionLocation = glGetAttribLocation(program, "position");
3597     ASSERT_NE(-1, positionLocation);
3598     setupQuadVertexBuffer(0.5f, 1.0f);
3599     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
3600     glEnableVertexAttribArray(positionLocation);
3601 
3602     std::array<GLfloat, 4> testValues = {{1, 2, 3, 4}};
3603     for (GLfloat testValue : testValues)
3604     {
3605         glUniform1f(uniLoc, testValue);
3606         glVertexAttrib1f(attribLoc, testValue);
3607         glDrawArrays(GL_TRIANGLES, 0, 6);
3608         ASSERT_GL_NO_ERROR();
3609         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3610     }
3611 }
3612 
3613 // Test that even inactive attributes are taken into account when checking for aliasing in case the
3614 // shader version is >= 3.00. GLSL ES 3.00.6 section 12.46.
TEST_P(VertexAttributeTestES3,InactiveAttributeAliasing)3615 TEST_P(VertexAttributeTestES3, InactiveAttributeAliasing)
3616 {
3617     constexpr char vertexShader[] =
3618         R"(#version 300 es
3619         precision mediump float;
3620         in vec4 input_active;
3621         in vec4 input_unused;
3622         void main()
3623         {
3624             gl_Position = input_active;
3625         })";
3626 
3627     constexpr char fragmentShader[] =
3628         R"(#version 300 es
3629         precision mediump float;
3630         out vec4 color;
3631         void main()
3632         {
3633             color = vec4(0.0);
3634         })";
3635 
3636     ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3637     glBindAttribLocation(program, 0, "input_active");
3638     glBindAttribLocation(program, 0, "input_unused");
3639     glLinkProgram(program);
3640     EXPECT_GL_NO_ERROR();
3641     GLint linkStatus = 0;
3642     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
3643     EXPECT_GL_FALSE(linkStatus);
3644 }
3645 
3646 // Test that enabling inactive attributes doesn't cause a crash
3647 // shader version is >= 3.00
TEST_P(VertexAttributeTestES3,EnabledButInactiveAttributes)3648 TEST_P(VertexAttributeTestES3, EnabledButInactiveAttributes)
3649 {
3650     // This is similar to runtest(), and the test is disabled there
3651     ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
3652 
3653     constexpr char testVertexShaderSource[] =
3654         R"(#version 300 es
3655 precision mediump float;
3656 in vec4 position;
3657 layout(location = 1) in vec4 test;
3658 layout(location = 2) in vec4 unused1;
3659 layout(location = 3) in vec4 unused2;
3660 layout(location = 4) in vec4 unused3;
3661 layout(location = 5) in vec4 expected;
3662 out vec4 color;
3663 void main(void)
3664 {
3665     gl_Position = position;
3666     vec4 threshold = max(abs(expected) * 0.01, 1.0 / 64.0);
3667     color = vec4(lessThanEqual(abs(test - expected), threshold));
3668 })";
3669 
3670     // Same as previous one, except it uses unused1/2 instead of test/expected, leaving unused3
3671     // unused
3672     constexpr char testVertexShader2Source[] =
3673         R"(#version 300 es
3674 precision mediump float;
3675 in vec4 position;
3676 layout(location = 1) in vec4 test;
3677 layout(location = 2) in vec4 unused1;
3678 layout(location = 3) in vec4 unused2;
3679 layout(location = 4) in vec4 unused3;
3680 layout(location = 5) in vec4 expected;
3681 out vec4 color;
3682 void main(void)
3683 {
3684     gl_Position = position;
3685     vec4 threshold = max(abs(unused2) * 0.01, 1.0 / 64.0);
3686     color = vec4(lessThanEqual(abs(unused1 - unused2), threshold));
3687 })";
3688 
3689     constexpr char testFragmentShaderSource[] =
3690         R"(#version 300 es
3691 precision mediump float;
3692 in vec4 color;
3693 out vec4 out_color;
3694 void main()
3695 {
3696     out_color = color;
3697 })";
3698 
3699     std::array<GLubyte, kVertexCount> inputData = {
3700         {0, 1, 2, 3, 4, 5, 6, 7, 125, 126, 127, 128, 129, 250, 251, 252, 253, 254, 255}};
3701     std::array<GLubyte, kVertexCount> inputData2;
3702     std::array<GLfloat, kVertexCount> expectedData;
3703     std::array<GLfloat, kVertexCount> expectedData2;
3704     for (size_t i = 0; i < kVertexCount; i++)
3705     {
3706         expectedData[i]  = inputData[i];
3707         inputData2[i]    = inputData[i] > 128 ? inputData[i] - 1 : inputData[i] + 1;
3708         expectedData2[i] = inputData2[i];
3709     }
3710 
3711     // Setup the program
3712     mProgram = CompileProgram(testVertexShaderSource, testFragmentShaderSource);
3713     ASSERT_NE(0u, mProgram);
3714 
3715     mTestAttrib = glGetAttribLocation(mProgram, "test");
3716     ASSERT_EQ(1, mTestAttrib);
3717     mExpectedAttrib = glGetAttribLocation(mProgram, "expected");
3718     ASSERT_EQ(5, mExpectedAttrib);
3719 
3720     GLint unused1Attrib = 2;
3721     GLint unused2Attrib = 3;
3722     GLint unused3Attrib = 4;
3723 
3724     // Test enabling an unused attribute before glUseProgram
3725     glEnableVertexAttribArray(unused3Attrib);
3726 
3727     glUseProgram(mProgram);
3728 
3729     // Setup the test data
3730     TestData data(GL_UNSIGNED_BYTE, GL_FALSE, Source::IMMEDIATE, inputData.data(),
3731                   expectedData.data());
3732     setupTest(data, 1);
3733 
3734     // Test enabling an unused attribute after glUseProgram
3735     glVertexAttribPointer(unused1Attrib, 1, data.type, data.normalized, 0, inputData2.data());
3736     glEnableVertexAttribArray(unused1Attrib);
3737 
3738     glVertexAttribPointer(unused2Attrib, 1, GL_FLOAT, GL_FALSE, 0, expectedData2.data());
3739     glEnableVertexAttribArray(unused2Attrib);
3740 
3741     // Run the test.  This shouldn't use the unused attributes.  Note that one of them is nullptr
3742     // which can cause a crash on certain platform-driver combination.
3743     drawQuad(mProgram, "position", 0.5f);
3744     checkPixels();
3745 
3746     // Now test with the same attributes enabled, but with a program with different attributes
3747     // active
3748     mProgram = CompileProgram(testVertexShader2Source, testFragmentShaderSource);
3749     ASSERT_NE(0u, mProgram);
3750 
3751     // Make sure all the attributes are in the same location
3752     ASSERT_EQ(glGetAttribLocation(mProgram, "unused1"), unused1Attrib);
3753     ASSERT_EQ(glGetAttribLocation(mProgram, "unused2"), unused2Attrib);
3754 
3755     glUseProgram(mProgram);
3756 
3757     // Run the test again.  unused1/2 were disabled in the previous run (as they were inactive in
3758     // the shader), but should be re-enabled now.
3759     drawQuad(mProgram, "position", 0.5f);
3760     checkPixels();
3761 }
3762 
3763 // Test that default integer attribute works correctly even if there is a gap in
3764 // attribute locations.
TEST_P(VertexAttributeTestES3,DefaultIntAttribWithGap)3765 TEST_P(VertexAttributeTestES3, DefaultIntAttribWithGap)
3766 {
3767     constexpr char kVertexShader[] = R"(#version 300 es
3768 layout(location = 0) in vec2 position;
3769 layout(location = 3) in int actualValue;
3770 uniform int expectedValue;
3771 out float result;
3772 void main()
3773 {
3774     result = (actualValue == expectedValue) ? 1.0 : 0.0;
3775     gl_Position = vec4(position, 0, 1);
3776 })";
3777 
3778     constexpr char kFragmentShader[] = R"(#version 300 es
3779 in mediump float result;
3780 layout(location = 0) out lowp vec4 out_color;
3781 void main()
3782 {
3783     out_color = result > 0.0 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
3784 })";
3785 
3786     ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
3787 
3788     // Re-link the program to update the attribute locations
3789     glLinkProgram(program);
3790     ASSERT_TRUE(CheckLinkStatusAndReturnProgram(program, true));
3791 
3792     glUseProgram(program);
3793 
3794     GLint uniLoc = glGetUniformLocation(program, "expectedValue");
3795     ASSERT_NE(-1, uniLoc);
3796 
3797     glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
3798 
3799     setupQuadVertexBuffer(0.5f, 1.0f);
3800     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
3801     glEnableVertexAttribArray(0);
3802 
3803     std::array<GLint, 4> testValues = {{1, 2, 3, 4}};
3804     for (GLfloat testValue : testValues)
3805     {
3806         glUniform1i(uniLoc, testValue);
3807         glVertexAttribI4i(3, testValue, 0, 0, 0);
3808         glDrawArrays(GL_TRIANGLES, 0, 6);
3809         ASSERT_GL_NO_ERROR();
3810         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3811     }
3812 }
3813 
3814 // Test that when three vertex attribute indices are enabled, but only two attributes among them
3815 // include data via glVertexAttribPointer(), there is no crash.
TEST_P(VertexAttributeTest,VertexAttribPointerCopyBufferFromInvalidAddress)3816 TEST_P(VertexAttributeTest, VertexAttribPointerCopyBufferFromInvalidAddress)
3817 {
3818     const GLfloat vertices[] = {
3819         // position   // color                // texCoord
3820         -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,  // Lower left corner
3821         1.0f,  -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,  // Bottom right corner
3822         0.0f,  1.0f,  0.0f, 0.0f, 1.0f, 1.0f, 0.5f, 1.0f   // Top
3823     };
3824 
3825     constexpr char kVS[] = R"(
3826         attribute highp vec2 position;
3827         attribute mediump vec4 color;
3828         attribute highp vec2 texCoord;
3829         varying mediump vec4 fragColor;
3830         varying highp vec2 fragTexCoord;
3831         void main() {
3832             gl_Position = vec4(position, 0.0, 1.0);
3833             fragColor = color;
3834             fragTexCoord = texCoord;
3835         }
3836     )";
3837 
3838     constexpr char kFS[] = R"(
3839         precision mediump float;
3840         varying mediump vec4 fragColor;
3841         varying highp vec2 fragTexCoord;
3842         void main() {
3843            if (fragTexCoord.x > 0.5) {
3844                 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
3845            } else {
3846                 gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
3847            }
3848         }
3849     )";
3850 
3851     mProgram = CompileProgram(kVS, kFS);
3852     ASSERT_NE(0u, mProgram);
3853     glBindAttribLocation(mProgram, 0, "position");
3854     glBindAttribLocation(mProgram, 1, "color");
3855     glBindAttribLocation(mProgram, 2, "texCoord");
3856     glUseProgram(mProgram);
3857     EXPECT_GL_NO_ERROR();
3858 
3859     glGenBuffers(1, &mBuffer);
3860     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
3861     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
3862     EXPECT_GL_NO_ERROR();
3863 
3864     glEnableVertexAttribArray(0);
3865     glEnableVertexAttribArray(1);
3866     glEnableVertexAttribArray(2);
3867     EXPECT_GL_NO_ERROR();
3868 
3869     glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid *)0);
3870     // Missing VertexAttribPointer at index 1
3871     glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat),
3872                           (GLvoid *)(6 * sizeof(GLfloat)));
3873 
3874     glDrawArrays(GL_TRIANGLES, 0, 3);
3875     EXPECT_GL_NO_ERROR();
3876 
3877     glDisableVertexAttribArray(0);
3878     glDisableVertexAttribArray(1);
3879     glDisableVertexAttribArray(2);
3880     EXPECT_GL_NO_ERROR();
3881 }
3882 
3883 // Test that default unsigned integer attribute works correctly even if there is a gap in
3884 // attribute locations.
TEST_P(VertexAttributeTestES3,DefaultUIntAttribWithGap)3885 TEST_P(VertexAttributeTestES3, DefaultUIntAttribWithGap)
3886 {
3887     constexpr char kVertexShader[] = R"(#version 300 es
3888 layout(location = 0) in vec2 position;
3889 layout(location = 3) in uint actualValue;
3890 uniform uint expectedValue;
3891 out float result;
3892 void main()
3893 {
3894     result = (actualValue == expectedValue) ? 1.0 : 0.0;
3895     gl_Position = vec4(position, 0, 1);
3896 })";
3897 
3898     constexpr char kFragmentShader[] = R"(#version 300 es
3899 in mediump float result;
3900 layout(location = 0) out lowp vec4 out_color;
3901 void main()
3902 {
3903     out_color = result > 0.0 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
3904 })";
3905 
3906     ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
3907 
3908     // Re-link the program to update the attribute locations
3909     glLinkProgram(program);
3910     ASSERT_TRUE(CheckLinkStatusAndReturnProgram(program, true));
3911 
3912     glUseProgram(program);
3913 
3914     GLint uniLoc = glGetUniformLocation(program, "expectedValue");
3915     ASSERT_NE(-1, uniLoc);
3916 
3917     glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
3918 
3919     setupQuadVertexBuffer(0.5f, 1.0f);
3920     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
3921     glEnableVertexAttribArray(0);
3922 
3923     std::array<GLuint, 4> testValues = {{1, 2, 3, 4}};
3924     for (GLfloat testValue : testValues)
3925     {
3926         glUniform1ui(uniLoc, testValue);
3927         glVertexAttribI4ui(3, testValue, 0, 0, 0);
3928         glDrawArrays(GL_TRIANGLES, 0, 6);
3929         ASSERT_GL_NO_ERROR();
3930         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3931     }
3932 }
3933 
3934 // Tests that large strides that read past the end of the buffer work correctly.
3935 // Requires ES 3.1 to query MAX_VERTEX_ATTRIB_STRIDE.
TEST_P(VertexAttributeTestES31,LargeStride)3936 TEST_P(VertexAttributeTestES31, LargeStride)
3937 {
3938     struct Vertex
3939     {
3940         Vector4 position;
3941         Vector2 color;
3942     };
3943 
3944     constexpr uint32_t kColorOffset = offsetof(Vertex, color);
3945 
3946     // Get MAX_VERTEX_ATTRIB_STRIDE.
3947     GLint maxStride;
3948     glGetIntegerv(GL_MAX_VERTEX_ATTRIB_STRIDE, &maxStride);
3949 
3950     uint32_t bufferSize  = static_cast<uint32_t>(maxStride);
3951     uint32_t stride      = sizeof(Vertex);
3952     uint32_t numVertices = bufferSize / stride;
3953 
3954     // The last vertex fits in the buffer size. The last vertex stride extends past it.
3955     ASSERT_LT(numVertices * stride, bufferSize);
3956     ASSERT_GT(numVertices * stride + kColorOffset, bufferSize);
3957 
3958     RNG rng(0);
3959 
3960     std::vector<Vertex> vertexData(bufferSize, {Vector4(), Vector2()});
3961     std::vector<GLColor> expectedColors;
3962     for (uint32_t vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex)
3963     {
3964         int x = vertexIndex % getWindowWidth();
3965         int y = vertexIndex / getWindowWidth();
3966 
3967         // Generate and clamp a 2 component vector.
3968         Vector4 randomVec4 = RandomVec4(rng.randomInt(), 0.0f, 1.0f);
3969         GLColor randomColor(randomVec4);
3970         randomColor[2]     = 0;
3971         randomColor[3]     = 255;
3972         Vector4 clampedVec = randomColor.toNormalizedVector();
3973 
3974         vertexData[vertexIndex] = {Vector4(x, y, 0.0f, 1.0f),
3975                                    Vector2(clampedVec[0], clampedVec[1])};
3976         expectedColors.push_back(randomColor);
3977     }
3978 
3979     GLBuffer buffer;
3980     glBindBuffer(GL_ARRAY_BUFFER, buffer);
3981     glBufferData(GL_ARRAY_BUFFER, bufferSize, vertexData.data(), GL_STATIC_DRAW);
3982 
3983     vertexData.resize(numVertices);
3984 
3985     constexpr char kVS[] = R"(#version 310 es
3986 in vec4 pos;
3987 in vec2 color;
3988 out vec2 vcolor;
3989 void main()
3990 {
3991     vcolor = color;
3992     gl_Position = vec4(((pos.x + 0.5) / 64.0) - 1.0, ((pos.y + 0.5) / 64.0) - 1.0, 0, 1);
3993     gl_PointSize = 1.0;
3994 })";
3995 
3996     constexpr char kFS[] = R"(#version 310 es
3997 precision mediump float;
3998 in vec2 vcolor;
3999 out vec4 fcolor;
4000 void main()
4001 {
4002     fcolor = vec4(vcolor, 0.0, 1.0);
4003 })";
4004 
4005     ANGLE_GL_PROGRAM(program, kVS, kFS);
4006     glUseProgram(program);
4007 
4008     GLint posLoc = glGetAttribLocation(program, "pos");
4009     ASSERT_NE(-1, posLoc);
4010     GLint colorLoc = glGetAttribLocation(program, "color");
4011     ASSERT_NE(-1, colorLoc);
4012 
4013     glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, stride, nullptr);
4014     glEnableVertexAttribArray(posLoc);
4015     glVertexAttribPointer(colorLoc, 2, GL_FLOAT, GL_FALSE, stride,
4016                           reinterpret_cast<GLvoid *>(static_cast<uintptr_t>(kColorOffset)));
4017     glEnableVertexAttribArray(colorLoc);
4018 
4019     glDrawArrays(GL_POINTS, 0, numVertices);
4020 
4021     // Validate pixels.
4022     std::vector<GLColor> actualColors(getWindowWidth() * getWindowHeight());
4023     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
4024                  actualColors.data());
4025 
4026     actualColors.resize(numVertices);
4027 
4028     ASSERT_GL_NO_ERROR();
4029     EXPECT_EQ(expectedColors, actualColors);
4030 }
4031 
makeMismatchingSignsTestVS(uint32_t attribCount,uint16_t signedMask)4032 std::string VertexAttributeTestES31::makeMismatchingSignsTestVS(uint32_t attribCount,
4033                                                                 uint16_t signedMask)
4034 {
4035     std::ostringstream shader;
4036 
4037     shader << R"(#version 310 es
4038 precision highp float;
4039 
4040 // The signedness is determined by |signedMask|.
4041 )";
4042 
4043     for (uint32_t i = 0; i < attribCount; ++i)
4044     {
4045         shader << "in highp " << ((signedMask >> i & 1) == 0 ? "u" : "i") << "vec4 attrib" << i
4046                << ";\n";
4047     }
4048 
4049     shader << "flat out highp uvec4 v[" << attribCount << "];\n";
4050 
4051     shader << R"(
4052 void main() {
4053 )";
4054 
4055     for (uint32_t i = 0; i < attribCount; ++i)
4056     {
4057         shader << "v[" << i << "] = uvec4(attrib" << i << ");\n";
4058     }
4059 
4060     shader << R"(
4061     // gl_VertexID    x    y
4062     //      0        -1   -1
4063     //      1         1   -1
4064     //      2        -1    1
4065     //      3         1    1
4066     int bit0 = gl_VertexID & 1;
4067     int bit1 = gl_VertexID >> 1;
4068     gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, gl_VertexID % 2 == 0 ? -1 : 1, 1);
4069 })";
4070 
4071     return shader.str();
4072 }
4073 
makeMismatchingSignsTestFS(uint32_t attribCount)4074 std::string VertexAttributeTestES31::makeMismatchingSignsTestFS(uint32_t attribCount)
4075 {
4076     std::ostringstream shader;
4077 
4078     shader << R"(#version 310 es
4079 precision highp float;
4080 )";
4081 
4082     shader << "flat in highp uvec4 v[" << attribCount << "];\n";
4083 
4084     shader << R"(out vec4 fragColor;
4085 uniform vec4 colorScale;
4086 
4087 bool isOk(uvec4 inputVarying, uint index)
4088 {
4089     return inputVarying.x == index &&
4090         inputVarying.y == index * 2u &&
4091         inputVarying.z == index + 1u &&
4092         inputVarying.w == index + 0x12345u;
4093 }
4094 
4095 void main()
4096 {
4097     bool result = true;
4098 )";
4099     shader << "    for (uint index = 0u; index < " << attribCount << "u; ++index)\n";
4100     shader << R"({
4101         result = result && isOk(v[index], index);
4102     }
4103 
4104     fragColor = vec4(result) * colorScale;
4105 })";
4106 
4107     return shader.str();
4108 }
4109 
setupVertexAttribPointersForMismatchSignsTest(uint16_t currentSignedMask,uint16_t toggleMask)4110 uint16_t VertexAttributeTestES31::setupVertexAttribPointersForMismatchSignsTest(
4111     uint16_t currentSignedMask,
4112     uint16_t toggleMask)
4113 {
4114     uint16_t newSignedMask = currentSignedMask ^ toggleMask;
4115 
4116     for (uint32_t i = 0; i < 16; ++i)
4117     {
4118         if ((toggleMask >> i & 1) == 0)
4119         {
4120             continue;
4121         }
4122 
4123         const GLenum type = (newSignedMask >> i & 1) == 0 ? GL_UNSIGNED_INT : GL_INT;
4124         glVertexAttribIPointer(i, 4, type, sizeof(GLuint[4]),
4125                                reinterpret_cast<const void *>(sizeof(GLuint[4][4]) * i));
4126     }
4127 
4128     return newSignedMask;
4129 }
4130 
4131 // Test changing between matching and mismatching signedness of vertex attributes, when the
4132 // attribute changes type.
TEST_P(VertexAttributeTestES31,MismatchingSignsChangingAttributeType)4133 TEST_P(VertexAttributeTestES31, MismatchingSignsChangingAttributeType)
4134 {
4135     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_relaxed_vertex_attribute_type"));
4136 
4137     // GL supports a minimum of 16 vertex attributes, and gl_VertexID is counted as one.
4138     // The signedness pattern used here is:
4139     //
4140     //   0                14
4141     //   iiui uuii iuui uui
4142     //
4143     // Which is chosen such that there's no clear repeating / mirror pattern.
4144     const std::string vs = makeMismatchingSignsTestVS(15, 0x49CB);
4145     const std::string fs = makeMismatchingSignsTestFS(15);
4146 
4147     ANGLE_GL_PROGRAM(program, vs.c_str(), fs.c_str());
4148     for (uint32_t i = 0; i < 15; ++i)
4149     {
4150         char attribName[20];
4151         snprintf(attribName, sizeof(attribName), "attrib%u\n", i);
4152         glBindAttribLocation(program, i, attribName);
4153     }
4154     glLinkProgram(program);
4155     glUseProgram(program);
4156     ASSERT_GL_NO_ERROR();
4157 
4158     GLint colorScaleLoc = glGetUniformLocation(program, "colorScale");
4159     ASSERT_NE(-1, colorScaleLoc);
4160 
4161     GLuint data[15][4][4];
4162     for (GLuint i = 0; i < 15; ++i)
4163     {
4164         for (GLuint j = 0; j < 4; ++j)
4165         {
4166             // Match the expectation in the shader
4167             data[i][j][0] = i;
4168             data[i][j][1] = i * 2;
4169             data[i][j][2] = i + 1;
4170             data[i][j][3] = i + 0x12345;
4171         }
4172     }
4173 
4174     GLBuffer buffer;
4175     glBindBuffer(GL_ARRAY_BUFFER, buffer);
4176     glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
4177 
4178     // Randomly match and mismatch the component type
4179     uint16_t signedMask = setupVertexAttribPointersForMismatchSignsTest(0x0FA5, 0x7FFF);
4180 
4181     for (uint32_t i = 0; i < 15; ++i)
4182     {
4183         glEnableVertexAttribArray(i);
4184     }
4185 
4186     glClearColor(0, 0, 0, 0);
4187     glClear(GL_COLOR_BUFFER_BIT);
4188 
4189     glEnable(GL_BLEND);
4190     glBlendFunc(GL_ONE, GL_ONE);
4191 
4192     glUniform4f(colorScaleLoc, 1, 0, 0, 0);
4193     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4194 
4195     // Modify the attributes randomly and make sure tests still pass
4196 
4197     signedMask = setupVertexAttribPointersForMismatchSignsTest(signedMask, 0x3572);
4198     glUniform4f(colorScaleLoc, 0, 1, 0, 0);
4199     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4200 
4201     signedMask = setupVertexAttribPointersForMismatchSignsTest(signedMask, 0x4B1C);
4202     glUniform4f(colorScaleLoc, 0, 0, 1, 0);
4203     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4204 
4205     signedMask = setupVertexAttribPointersForMismatchSignsTest(signedMask, 0x19D6);
4206     glUniform4f(colorScaleLoc, 0, 0, 0, 1);
4207     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4208 
4209     // All channels must be 1
4210     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::white);
4211     ASSERT_GL_NO_ERROR();
4212 }
4213 
4214 // Test changing between matching and mismatching signedness of vertex attributes, when the
4215 // program itself changes the type.
TEST_P(VertexAttributeTestES31,MismatchingSignsChangingProgramType)4216 TEST_P(VertexAttributeTestES31, MismatchingSignsChangingProgramType)
4217 {
4218     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_relaxed_vertex_attribute_type"));
4219 
4220     // GL supports a minimum of 16 vertex attributes, and gl_VertexID is counted as one.
4221     constexpr uint32_t kAttribCount[4]      = {12, 9, 15, 7};
4222     constexpr uint32_t kAttribSignedMask[4] = {0x94f, 0x6A, 0x765B, 0x29};
4223 
4224     GLProgram programs[4];
4225 
4226     for (uint32_t progIndex = 0; progIndex < 4; ++progIndex)
4227     {
4228         const std::string vs =
4229             makeMismatchingSignsTestVS(kAttribCount[progIndex], kAttribSignedMask[progIndex]);
4230         const std::string fs = makeMismatchingSignsTestFS(kAttribCount[progIndex]);
4231 
4232         programs[progIndex].makeRaster(vs.c_str(), fs.c_str());
4233         for (uint32_t i = 0; i < kAttribCount[progIndex]; ++i)
4234         {
4235             char attribName[20];
4236             snprintf(attribName, sizeof(attribName), "attrib%u\n", i);
4237             glBindAttribLocation(programs[progIndex], i, attribName);
4238         }
4239         glLinkProgram(programs[progIndex]);
4240         glUseProgram(programs[progIndex]);
4241         ASSERT_GL_NO_ERROR();
4242     }
4243 
4244     GLuint data[15][4][4];
4245     for (GLuint i = 0; i < 15; ++i)
4246     {
4247         for (GLuint j = 0; j < 4; ++j)
4248         {
4249             // Match the expectation in the shader
4250             data[i][j][0] = i;
4251             data[i][j][1] = i * 2;
4252             data[i][j][2] = i + 1;
4253             data[i][j][3] = i + 0x12345;
4254         }
4255     }
4256 
4257     GLBuffer buffer;
4258     glBindBuffer(GL_ARRAY_BUFFER, buffer);
4259     glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
4260 
4261     // Randomly match and mismatch the component type
4262     setupVertexAttribPointersForMismatchSignsTest(0x55F8, 0x7FFF);
4263 
4264     for (uint32_t i = 0; i < 15; ++i)
4265     {
4266         glEnableVertexAttribArray(i);
4267     }
4268 
4269     glClearColor(0, 0, 0, 0);
4270     glClear(GL_COLOR_BUFFER_BIT);
4271 
4272     glEnable(GL_BLEND);
4273     glBlendFunc(GL_ONE, GL_ONE);
4274 
4275     glUseProgram(programs[0]);
4276     GLint colorScaleLoc = glGetUniformLocation(programs[0], "colorScale");
4277     ASSERT_NE(-1, colorScaleLoc);
4278     glUniform4f(colorScaleLoc, 1, 0, 0, 0);
4279     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4280 
4281     // Change the program, which have randomly different attribute component types and make sure
4282     // tests still pass
4283 
4284     glUseProgram(programs[1]);
4285     colorScaleLoc = glGetUniformLocation(programs[1], "colorScale");
4286     ASSERT_NE(-1, colorScaleLoc);
4287     glUniform4f(colorScaleLoc, 0, 1, 0, 0);
4288     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4289 
4290     glUseProgram(programs[2]);
4291     colorScaleLoc = glGetUniformLocation(programs[2], "colorScale");
4292     ASSERT_NE(-1, colorScaleLoc);
4293     glUniform4f(colorScaleLoc, 0, 0, 1, 0);
4294     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4295 
4296     glUseProgram(programs[3]);
4297     colorScaleLoc = glGetUniformLocation(programs[3], "colorScale");
4298     ASSERT_NE(-1, colorScaleLoc);
4299     glUniform4f(colorScaleLoc, 0, 0, 0, 1);
4300     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4301 
4302     // All channels must be 1
4303     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::white);
4304     ASSERT_GL_NO_ERROR();
4305 }
4306 
4307 // Test that aliasing attribute locations work with es 100 shaders.  Note that es 300 and above
4308 // don't allow vertex attribute aliasing.  This test excludes matrix types.
TEST_P(VertexAttributeTest,AliasingVectorAttribLocations)4309 TEST_P(VertexAttributeTest, AliasingVectorAttribLocations)
4310 {
4311     // http://anglebug.com/42263740
4312     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
4313 
4314     // http://anglebug.com/42262130
4315     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
4316 
4317     // http://anglebug.com/42262131
4318     ANGLE_SKIP_TEST_IF(IsD3D());
4319 
4320     // This test needs 10 total attributes. All backends support this except some old Android
4321     // devices.
4322     GLint maxVertexAttribs = 0;
4323     glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
4324     ANGLE_SKIP_TEST_IF(maxVertexAttribs < 10);
4325 
4326     constexpr char kVS[] = R"(attribute vec4 position;
4327 // 4 aliasing attributes
4328 attribute float attr0f;
4329 attribute vec2 attr0v2;
4330 attribute vec3 attr0v3;
4331 attribute vec4 attr0v4;
4332 const vec4 attr0Expected = vec4(0.1, 0.2, 0.3, 0.4);
4333 
4334 // 2 aliasing attributes
4335 attribute vec2 attr1v2;
4336 attribute vec3 attr1v3;
4337 const vec3 attr1Expected = vec3(0.5, 0.6, 0.7);
4338 
4339 // 2 aliasing attributes
4340 attribute vec4 attr2v4;
4341 attribute float attr2f;
4342 const vec4 attr2Expected = vec4(0.8, 0.85, 0.9, 0.95);
4343 
4344 // 2 aliasing attributes
4345 attribute float attr3f1;
4346 attribute float attr3f2;
4347 const float attr3Expected = 1.0;
4348 
4349 uniform float attr0Select;
4350 uniform float attr1Select;
4351 uniform float attr2Select;
4352 uniform float attr3Select;
4353 
4354 // Each channel controlled by success from each set of aliasing attributes.  If a channel is 0, the
4355 // attribute test has failed.  Otherwise it will be 0.25, 0.5, 0.75 or 1.0, depending on how many
4356 // channels there are in the compared attribute (except attr3).
4357 varying mediump vec4 color;
4358 void main()
4359 {
4360     gl_Position = position;
4361 
4362     vec4 result = vec4(0);
4363 
4364     if (attr0Select < 0.5)
4365         result.r = abs(attr0f - attr0Expected.x) < 0.01 ? 0.25 : 0.0;
4366     else if (attr0Select < 1.5)
4367         result.r = all(lessThan(abs(attr0v2 - attr0Expected.xy), vec2(0.01))) ? 0.5 : 0.0;
4368     else if (attr0Select < 2.5)
4369         result.r = all(lessThan(abs(attr0v3 - attr0Expected.xyz), vec3(0.01))) ? 0.75 : 0.0;
4370     else
4371         result.r = all(lessThan(abs(attr0v4 - attr0Expected), vec4(0.01 )))? 1.0 : 0.0;
4372 
4373     if (attr1Select < 0.5)
4374         result.g = all(lessThan(abs(attr1v2 - attr1Expected.xy), vec2(0.01 )))? 0.5 : 0.0;
4375     else
4376         result.g = all(lessThan(abs(attr1v3 - attr1Expected), vec3(0.01 )))? 0.75 : 0.0;
4377 
4378     if (attr2Select < 0.5)
4379         result.b = abs(attr2f - attr2Expected.x) < 0.01 ? 0.25 : 0.0;
4380     else
4381         result.b = all(lessThan(abs(attr2v4 - attr2Expected), vec4(0.01))) ? 1.0 : 0.0;
4382 
4383     if (attr3Select < 0.5)
4384         result.a = abs(attr3f1 - attr3Expected) < 0.01 ? 0.25 : 0.0;
4385     else
4386         result.a = abs(attr3f2 - attr3Expected) < 0.01 ? 0.5 : 0.0;
4387 
4388     color = result;
4389 })";
4390 
4391     constexpr char kFS[] = R"(varying mediump vec4 color;
4392     void main(void)
4393     {
4394         gl_FragColor = color;
4395     })";
4396 
4397     // Compile shaders.
4398     GLuint program = CompileProgram(kVS, kFS);
4399     ASSERT_NE(program, 0u);
4400 
4401     // Setup bindings.
4402     glBindAttribLocation(program, 0, "attr0f");
4403     glBindAttribLocation(program, 0, "attr0v2");
4404     glBindAttribLocation(program, 0, "attr0v3");
4405     glBindAttribLocation(program, 0, "attr0v4");
4406     glBindAttribLocation(program, 1, "attr1v2");
4407     glBindAttribLocation(program, 1, "attr1v3");
4408     glBindAttribLocation(program, 2, "attr2v4");
4409     glBindAttribLocation(program, 2, "attr2f");
4410     glBindAttribLocation(program, 3, "attr3f1");
4411     glBindAttribLocation(program, 3, "attr3f2");
4412     EXPECT_GL_NO_ERROR();
4413 
4414     // Link program and get uniform locations.
4415     glLinkProgram(program);
4416     glUseProgram(program);
4417     GLint attr0SelectLoc = glGetUniformLocation(program, "attr0Select");
4418     GLint attr1SelectLoc = glGetUniformLocation(program, "attr1Select");
4419     GLint attr2SelectLoc = glGetUniformLocation(program, "attr2Select");
4420     GLint attr3SelectLoc = glGetUniformLocation(program, "attr3Select");
4421     ASSERT_NE(-1, attr0SelectLoc);
4422     ASSERT_NE(-1, attr1SelectLoc);
4423     ASSERT_NE(-1, attr2SelectLoc);
4424     ASSERT_NE(-1, attr3SelectLoc);
4425     EXPECT_GL_NO_ERROR();
4426 
4427     // Set values for attributes.
4428     glVertexAttrib4f(0, 0.1f, 0.2f, 0.3f, 0.4f);
4429     glVertexAttrib3f(1, 0.5f, 0.6f, 0.7f);
4430     glVertexAttrib4f(2, 0.8f, 0.85f, 0.9f, 0.95f);
4431     glVertexAttrib1f(3, 1.0f);
4432     glDisableVertexAttribArray(0);
4433     glDisableVertexAttribArray(1);
4434     glDisableVertexAttribArray(2);
4435     glDisableVertexAttribArray(3);
4436     EXPECT_GL_NO_ERROR();
4437 
4438     // Go through different combination of attributes and make sure reading through every alias is
4439     // correctly handled.
4440     GLColor expected;
4441     for (uint32_t attr0Select = 0; attr0Select < 4; ++attr0Select)
4442     {
4443         glUniform1f(attr0SelectLoc, attr0Select);
4444         expected.R = attr0Select * 64 + 63;
4445 
4446         for (uint32_t attr1Select = 0; attr1Select < 2; ++attr1Select)
4447         {
4448             glUniform1f(attr1SelectLoc, attr1Select);
4449             expected.G = attr1Select * 64 + 127;
4450 
4451             for (uint32_t attr2Select = 0; attr2Select < 2; ++attr2Select)
4452             {
4453                 glUniform1f(attr2SelectLoc, attr2Select);
4454                 expected.B = attr2Select * 192 + 63;
4455 
4456                 for (uint32_t attr3Select = 0; attr3Select < 2; ++attr3Select)
4457                 {
4458                     glUniform1f(attr3SelectLoc, attr3Select);
4459                     expected.A = attr3Select * 64 + 63;
4460 
4461                     drawQuad(program, "position", 0.5f);
4462                     EXPECT_GL_NO_ERROR();
4463                     EXPECT_PIXEL_COLOR_NEAR(0, 0, expected, 1);
4464                 }
4465             }
4466         }
4467     }
4468 }
4469 
4470 // Test that aliasing attribute locations work with es 100 shaders.  Note that es 300 and above
4471 // don't allow vertex attribute aliasing.  This test includes matrix types.
TEST_P(VertexAttributeTest,AliasingMatrixAttribLocations)4472 TEST_P(VertexAttributeTest, AliasingMatrixAttribLocations)
4473 {
4474     // http://anglebug.com/42263740
4475     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
4476 
4477     // http://anglebug.com/42262130
4478     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
4479 
4480     // http://anglebug.com/42262131
4481     ANGLE_SKIP_TEST_IF(IsD3D());
4482 
4483     // This test needs 16 total attributes. All backends support this except some old Android
4484     // devices.
4485     GLint maxVertexAttribs = 0;
4486     glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
4487     ANGLE_SKIP_TEST_IF(maxVertexAttribs < 16);
4488 
4489     constexpr char kVS[] = R"(attribute vec4 position;
4490 // attributes aliasing location 0 and above
4491 attribute float attr0f;
4492 attribute mat3 attr0m3;
4493 attribute mat2 attr0m2;
4494 
4495 // attributes aliasing location 1 and above
4496 attribute vec4 attr1v4;
4497 
4498 // attributes aliasing location 2 and above
4499 attribute mat4 attr2m4;
4500 
4501 // attributes aliasing location 3 and above
4502 attribute mat2 attr3m2;
4503 
4504 // attributes aliasing location 5 and above
4505 attribute vec2 attr5v2;
4506 
4507 // In summary (attr prefix shortened to a):
4508 //
4509 // location 0: a0f a0m3[0] a0m2[0]
4510 // location 1:     a0m3[1] a0m2[1] a1v4
4511 // location 2:     a0m3[2]              a2m4[0]
4512 // location 3:                          a2m4[1] a3m2[0]
4513 // location 4:                          a2m4[2] a3m2[1]
4514 // location 5:                          a2m4[3]         a5v2
4515 
4516 const vec3 loc0Expected = vec3(0.05, 0.1, 0.15);
4517 const vec4 loc1Expected = vec4(0.2, 0.25, 0.3, 0.35);
4518 const vec4 loc2Expected = vec4(0.4, 0.45, 0.5, 0.55);
4519 const vec4 loc3Expected = vec4(0.6, 0.65, 0.7, 0.75);
4520 const vec4 loc4Expected = vec4(0.8, 0.85, 0.9, 0.95);
4521 const vec4 loc5Expected = vec4(0.25, 0.5, 0.75, 1.0);
4522 
4523 uniform float loc0Select;
4524 uniform float loc1Select;
4525 uniform float loc2Select;
4526 uniform float loc3Select;
4527 uniform float loc4Select;
4528 uniform float loc5Select;
4529 
4530 // Each channel controlled by success from each set of aliasing locations.  Locations 2 and 3
4531 // contribute to B together, while locations 4 and 5 contribute to A together.  If a channel is 0,
4532 // the attribute test has failed.  Otherwise it will be 1/N, 2/N, ..., 1, depending on how many
4533 // possible values there are for the controlling uniforms.
4534 varying mediump vec4 color;
4535 void main()
4536 {
4537     gl_Position = position;
4538 
4539     vec4 result = vec4(0);
4540 
4541     if (loc0Select < 0.5)
4542         result.r = abs(attr0f - loc0Expected.x) < 0.01 ? 0.333333 : 0.0;
4543     else if (loc0Select < 1.5)
4544         result.r = all(lessThan(abs(attr0m2[0] - loc0Expected.xy), vec2(0.01))) ? 0.666667 : 0.0;
4545     else
4546         result.r = all(lessThan(abs(attr0m3[0] - loc0Expected), vec3(0.01))) ? 1.0 : 0.0;
4547 
4548     if (loc1Select < 0.5)
4549         result.g = all(lessThan(abs(attr0m3[1] - loc1Expected.xyz), vec3(0.01))) ? 0.333333 : 0.0;
4550     else if (loc1Select < 1.5)
4551         result.g = all(lessThan(abs(attr0m2[1] - loc1Expected.xy), vec2(0.01))) ? 0.666667 : 0.0;
4552     else
4553         result.g = all(lessThan(abs(attr1v4 - loc1Expected), vec4(0.01))) ? 1.0 : 0.0;
4554 
4555     bool loc2Ok = false;
4556     bool loc3Ok = false;
4557 
4558     if (loc2Select < 0.5)
4559         loc2Ok = all(lessThan(abs(attr0m3[2] - loc2Expected.xyz), vec3(0.01)));
4560     else
4561         loc2Ok = all(lessThan(abs(attr2m4[0] - loc2Expected), vec4(0.01)));
4562 
4563     if (loc3Select < 0.5)
4564         loc3Ok = all(lessThan(abs(attr2m4[1] - loc3Expected), vec4(0.01)));
4565     else
4566         loc3Ok = all(lessThan(abs(attr3m2[0] - loc3Expected.xy), vec2(0.01)));
4567 
4568     if (loc2Ok && loc3Ok)
4569     {
4570         if (loc2Select < 0.5)
4571             if (loc3Select < 0.5)
4572                 result.b = 0.25;
4573             else
4574                 result.b = 0.5;
4575         else
4576             if (loc3Select < 0.5)
4577                 result.b = 0.75;
4578             else
4579                 result.b = 1.0;
4580     }
4581 
4582     bool loc4Ok = false;
4583     bool loc5Ok = false;
4584 
4585     if (loc4Select < 0.5)
4586         loc4Ok = all(lessThan(abs(attr2m4[2] - loc4Expected), vec4(0.01)));
4587     else
4588         loc4Ok = all(lessThan(abs(attr3m2[1] - loc4Expected.xy), vec2(0.01)));
4589 
4590     if (loc5Select < 0.5)
4591         loc5Ok = all(lessThan(abs(attr2m4[3] - loc5Expected), vec4(0.01)));
4592     else
4593         loc5Ok = all(lessThan(abs(attr5v2 - loc5Expected.xy), vec2(0.01)));
4594 
4595     if (loc4Ok && loc5Ok)
4596     {
4597         if (loc4Select < 0.5)
4598             if (loc5Select < 0.5)
4599                 result.a = 0.25;
4600             else
4601                 result.a = 0.5;
4602         else
4603             if (loc5Select < 0.5)
4604                 result.a = 0.75;
4605             else
4606                 result.a = 1.0;
4607     }
4608 
4609     color = result;
4610 })";
4611 
4612     constexpr char kFS[] = R"(varying mediump vec4 color;
4613     void main(void)
4614     {
4615         gl_FragColor = color;
4616     })";
4617 
4618     // Compile shaders.
4619     GLuint program = CompileProgram(kVS, kFS);
4620     ASSERT_NE(program, 0u);
4621 
4622     // Setup bindings.
4623     glBindAttribLocation(program, 0, "attr0f");
4624     glBindAttribLocation(program, 0, "attr0m3");
4625     glBindAttribLocation(program, 0, "attr0m2");
4626     glBindAttribLocation(program, 1, "attr1v4");
4627     glBindAttribLocation(program, 2, "attr2m4");
4628     glBindAttribLocation(program, 3, "attr3m2");
4629     glBindAttribLocation(program, 5, "attr5v2");
4630     EXPECT_GL_NO_ERROR();
4631 
4632     // Link program and get uniform locations.
4633     glLinkProgram(program);
4634     glUseProgram(program);
4635     EXPECT_GL_NO_ERROR();
4636 
4637     GLint loc0SelectLoc = glGetUniformLocation(program, "loc0Select");
4638     GLint loc1SelectLoc = glGetUniformLocation(program, "loc1Select");
4639     GLint loc2SelectLoc = glGetUniformLocation(program, "loc2Select");
4640     GLint loc3SelectLoc = glGetUniformLocation(program, "loc3Select");
4641     GLint loc4SelectLoc = glGetUniformLocation(program, "loc4Select");
4642     GLint loc5SelectLoc = glGetUniformLocation(program, "loc5Select");
4643     ASSERT_NE(-1, loc0SelectLoc);
4644     ASSERT_NE(-1, loc1SelectLoc);
4645     ASSERT_NE(-1, loc2SelectLoc);
4646     ASSERT_NE(-1, loc3SelectLoc);
4647     ASSERT_NE(-1, loc4SelectLoc);
4648     ASSERT_NE(-1, loc5SelectLoc);
4649     EXPECT_GL_NO_ERROR();
4650 
4651     // Set values for attributes.
4652     glVertexAttrib3f(0, 0.05, 0.1, 0.15);
4653     glVertexAttrib4f(1, 0.2, 0.25, 0.3, 0.35);
4654     glVertexAttrib4f(2, 0.4, 0.45, 0.5, 0.55);
4655     glVertexAttrib4f(3, 0.6, 0.65, 0.7, 0.75);
4656     glVertexAttrib4f(4, 0.8, 0.85, 0.9, 0.95);
4657     glVertexAttrib4f(5, 0.25, 0.5, 0.75, 1.0);
4658     glDisableVertexAttribArray(0);
4659     glDisableVertexAttribArray(1);
4660     glDisableVertexAttribArray(2);
4661     glDisableVertexAttribArray(3);
4662     glDisableVertexAttribArray(4);
4663     glDisableVertexAttribArray(5);
4664     EXPECT_GL_NO_ERROR();
4665 
4666     // Go through different combination of attributes and make sure reading through every alias is
4667     // correctly handled.
4668     GLColor expected;
4669     for (uint32_t loc0Select = 0; loc0Select < 3; ++loc0Select)
4670     {
4671         glUniform1f(loc0SelectLoc, loc0Select);
4672         expected.R = loc0Select * 85 + 85;
4673 
4674         for (uint32_t loc1Select = 0; loc1Select < 3; ++loc1Select)
4675         {
4676             glUniform1f(loc1SelectLoc, loc1Select);
4677             expected.G = loc1Select * 85 + 85;
4678 
4679             for (uint32_t loc2Select = 0; loc2Select < 2; ++loc2Select)
4680             {
4681                 glUniform1f(loc2SelectLoc, loc2Select);
4682 
4683                 for (uint32_t loc3Select = 0; loc3Select < 2; ++loc3Select)
4684                 {
4685                     glUniform1f(loc3SelectLoc, loc3Select);
4686                     expected.B = (loc2Select << 1 | loc3Select) * 64 + 63;
4687 
4688                     for (uint32_t loc4Select = 0; loc4Select < 2; ++loc4Select)
4689                     {
4690                         glUniform1f(loc4SelectLoc, loc4Select);
4691 
4692                         for (uint32_t loc5Select = 0; loc5Select < 2; ++loc5Select)
4693                         {
4694                             glUniform1f(loc5SelectLoc, loc5Select);
4695                             expected.A = (loc4Select << 1 | loc5Select) * 64 + 63;
4696 
4697                             drawQuad(program, "position", 0.5f);
4698                             EXPECT_GL_NO_ERROR();
4699                             EXPECT_PIXEL_COLOR_NEAR(0, 0, expected, 1);
4700                         }
4701                     }
4702                 }
4703             }
4704         }
4705     }
4706 }
4707 
4708 // Test that aliasing attribute locations work with differing precisions.
TEST_P(VertexAttributeTest,AliasingVectorAttribLocationsDifferingPrecisions)4709 TEST_P(VertexAttributeTest, AliasingVectorAttribLocationsDifferingPrecisions)
4710 {
4711     // http://anglebug.com/42263740
4712     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
4713 
4714     // http://anglebug.com/42262130
4715     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
4716 
4717     // http://anglebug.com/42262131
4718     ANGLE_SKIP_TEST_IF(IsD3D());
4719 
4720     constexpr char kVS[] = R"(attribute vec4 position;
4721 // aliasing attributes.
4722 attribute mediump vec2 attr0v2;
4723 attribute highp vec3 attr0v3;
4724 const vec3 attr0Expected = vec3(0.125, 0.25, 0.375);
4725 
4726 // aliasing attributes.
4727 attribute highp vec2 attr1v2;
4728 attribute mediump vec3 attr1v3;
4729 const vec3 attr1Expected = vec3(0.5, 0.625, 0.75);
4730 
4731 uniform float attr0Select;
4732 uniform float attr1Select;
4733 
4734 // Each channel controlled by success from each set of aliasing attributes (R and G used only).  If
4735 // a channel is 0, the attribute test has failed.  Otherwise it will be 0.5 or 1.0.
4736 varying mediump vec4 color;
4737 void main()
4738 {
4739     gl_Position = position;
4740 
4741     vec4 result = vec4(0, 0, 0, 1);
4742 
4743     if (attr0Select < 0.5)
4744         result.r = all(lessThan(abs(attr0v2 - attr0Expected.xy), vec2(0.01))) ? 0.5 : 0.0;
4745     else
4746         result.r = all(lessThan(abs(attr0v3 - attr0Expected), vec3(0.01))) ? 1.0 : 0.0;
4747 
4748     if (attr1Select < 0.5)
4749         result.g = all(lessThan(abs(attr1v2 - attr1Expected.xy), vec2(0.01))) ? 0.5 : 0.0;
4750     else
4751         result.g = all(lessThan(abs(attr1v3 - attr1Expected), vec3(0.01))) ? 1.0 : 0.0;
4752 
4753     color = result;
4754 })";
4755 
4756     constexpr char kFS[] = R"(varying mediump vec4 color;
4757     void main(void)
4758     {
4759         gl_FragColor = color;
4760     })";
4761 
4762     // Compile shaders.
4763     GLuint program = CompileProgram(kVS, kFS);
4764     ASSERT_NE(program, 0u);
4765 
4766     // Setup bindings.
4767     glBindAttribLocation(program, 0, "attr0v2");
4768     glBindAttribLocation(program, 0, "attr0v3");
4769     glBindAttribLocation(program, 1, "attr1v2");
4770     glBindAttribLocation(program, 1, "attr1v3");
4771     EXPECT_GL_NO_ERROR();
4772 
4773     // Link program and get uniform locations.
4774     glLinkProgram(program);
4775     glUseProgram(program);
4776     GLint attr0SelectLoc = glGetUniformLocation(program, "attr0Select");
4777     GLint attr1SelectLoc = glGetUniformLocation(program, "attr1Select");
4778     ASSERT_NE(-1, attr0SelectLoc);
4779     ASSERT_NE(-1, attr1SelectLoc);
4780     EXPECT_GL_NO_ERROR();
4781 
4782     // Set values for attributes.
4783     glVertexAttrib3f(0, 0.125f, 0.25f, 0.375f);
4784     glVertexAttrib3f(1, 0.5f, 0.625f, 0.75f);
4785     glDisableVertexAttribArray(0);
4786     glDisableVertexAttribArray(1);
4787     EXPECT_GL_NO_ERROR();
4788 
4789     // Go through different combination of attributes and make sure reading through every alias is
4790     // correctly handled.
4791     GLColor expected;
4792     expected.B = 0;
4793     expected.A = 255;
4794     for (uint32_t attr0Select = 0; attr0Select < 2; ++attr0Select)
4795     {
4796         glUniform1f(attr0SelectLoc, attr0Select);
4797         expected.R = attr0Select * 128 + 127;
4798 
4799         for (uint32_t attr1Select = 0; attr1Select < 2; ++attr1Select)
4800         {
4801             glUniform1f(attr1SelectLoc, attr1Select);
4802             expected.G = attr1Select * 128 + 127;
4803 
4804             drawQuad(program, "position", 0.5f);
4805             EXPECT_GL_NO_ERROR();
4806             EXPECT_PIXEL_COLOR_NEAR(0, 0, expected, 1);
4807         }
4808     }
4809 }
4810 
4811 // Test that unsupported vertex format specified on non-existing attribute doesn't crash.
TEST_P(VertexAttributeTest,VertexFormatConversionOfNonExistingAttribute)4812 TEST_P(VertexAttributeTest, VertexFormatConversionOfNonExistingAttribute)
4813 {
4814     constexpr char kVS[] = R"(precision highp float;
4815 attribute vec3 attr1;
4816 void main(void) {
4817    gl_Position = vec4(attr1, 1.0);
4818 })";
4819 
4820     constexpr char kFS[] = R"(precision highp float;
4821 void main(void) {
4822    gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
4823 })";
4824 
4825     GLBuffer emptyBuffer;
4826     glBindBuffer(GL_ARRAY_BUFFER, emptyBuffer);
4827 
4828     ANGLE_GL_PROGRAM(program, kVS, kFS);
4829     glBindAttribLocation(program, 0, "attr1");
4830     glLinkProgram(program);
4831     ASSERT_TRUE(CheckLinkStatusAndReturnProgram(program, true));
4832     glUseProgram(program);
4833 
4834     // Use the RGB8 format for non-existing attribute 1.
4835     glEnableVertexAttribArray(1);
4836     glVertexAttribPointer(1, 3, GL_UNSIGNED_BYTE, false, 1, 0);
4837 
4838     glDrawArrays(GL_TRIANGLES, 0, 3);
4839     EXPECT_GL_NO_ERROR();
4840 }
4841 
4842 // Covers a bug with integer formats and an element size larger than the vertex stride.
TEST_P(VertexAttributeTestES3,StrideSmallerThanIntegerElementSize)4843 TEST_P(VertexAttributeTestES3, StrideSmallerThanIntegerElementSize)
4844 {
4845     constexpr char kVS[] = R"(#version 300 es
4846 in vec4 position;
4847 in ivec2 intAttrib;
4848 in vec2 floatAttrib;
4849 out vec4 colorVarying;
4850 void main()
4851 {
4852     gl_Position = position;
4853     if (vec2(intAttrib) == floatAttrib)
4854     {
4855         colorVarying = vec4(0, 1, 0, 1);
4856     }
4857     else
4858     {
4859         colorVarying = vec4(1, 0, 0, 1);
4860     }
4861 })";
4862 
4863     constexpr char kFS[] = R"(#version 300 es
4864 precision mediump float;
4865 in vec4 colorVarying;
4866 out vec4 fragColor;
4867 void main()
4868 {
4869     fragColor = colorVarying;
4870 })";
4871 
4872     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
4873     glUseProgram(testProgram);
4874 
4875     GLBuffer positionBuffer;
4876     {
4877         const std::array<Vector3, 6> &quadVerts = GetQuadVertices();
4878 
4879         glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
4880         glBufferData(GL_ARRAY_BUFFER, quadVerts.size() * sizeof(quadVerts[0]), quadVerts.data(),
4881                      GL_STATIC_DRAW);
4882 
4883         GLint posLoc = glGetAttribLocation(testProgram, "position");
4884         ASSERT_NE(posLoc, -1);
4885         glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4886         glEnableVertexAttribArray(posLoc);
4887     }
4888 
4889     GLBuffer intBuffer;
4890     {
4891         std::array<GLbyte, 12> intData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
4892 
4893         glBindBuffer(GL_ARRAY_BUFFER, intBuffer);
4894         glBufferData(GL_ARRAY_BUFFER, intData.size() * sizeof(intData[0]), intData.data(),
4895                      GL_STATIC_DRAW);
4896 
4897         GLint intLoc = glGetAttribLocation(testProgram, "intAttrib");
4898         ASSERT_NE(intLoc, -1);
4899         glVertexAttribIPointer(intLoc, 2, GL_BYTE, 1, nullptr);
4900         glEnableVertexAttribArray(intLoc);
4901     }
4902 
4903     GLBuffer floatBuffer;
4904     {
4905         std::array<GLfloat, 12> floatData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
4906 
4907         glBindBuffer(GL_ARRAY_BUFFER, floatBuffer);
4908         glBufferData(GL_ARRAY_BUFFER, floatData.size() * sizeof(floatData[0]), floatData.data(),
4909                      GL_STATIC_DRAW);
4910 
4911         GLint floatLoc = glGetAttribLocation(testProgram, "floatAttrib");
4912         ASSERT_NE(floatLoc, -1);
4913         glVertexAttribPointer(floatLoc, 2, GL_FLOAT, GL_FALSE, 4, nullptr);
4914         glEnableVertexAttribArray(floatLoc);
4915     }
4916 
4917     glDrawArrays(GL_TRIANGLES, 0, 6);
4918 
4919     ASSERT_GL_NO_ERROR();
4920 
4921     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::green);
4922 }
4923 
4924 // Test that pipeline is recreated properly when switching from ARRAY buffer to client buffer,
4925 // while removing client buffer. Bug observed in Dragonmania game.
TEST_P(VertexAttributeTestES31,ArrayToClientBufferStride)4926 TEST_P(VertexAttributeTestES31, ArrayToClientBufferStride)
4927 {
4928     constexpr char kVS[] = R"(#version 310 es
4929 precision highp float;
4930 in vec4 in_pos;
4931 in vec4 in_color;
4932 out vec4 color;
4933 void main(void) {
4934    gl_Position = in_pos;
4935    color = in_color;
4936 })";
4937 
4938     constexpr char kFS[] = R"(#version 310 es
4939 precision highp float;
4940 in vec4 color;
4941 out vec4 frag_color;
4942 void main(void) {
4943    frag_color = color;
4944 })";
4945     swapBuffers();
4946 
4947     ANGLE_GL_PROGRAM(program, kVS, kFS);
4948     glUseProgram(program);
4949     GLint posLoc   = glGetAttribLocation(program, "in_pos");
4950     GLint colorLoc = glGetAttribLocation(program, "in_color");
4951     ASSERT_NE(posLoc, -1);
4952     ASSERT_NE(colorLoc, -1);
4953 
4954     const std::array<Vector3, 6> &quadVerts = GetQuadVertices();
4955     // Data for packed attributes.
4956     std::array<float, ((3 + 4) * 6)> data;
4957 
4958     float kYellow[4] = {1.0f, 1.0f, 0.0f, 1.0f};
4959     float kGreen[4]  = {0.0f, 1.0f, 0.0f, 1.0f};
4960 
4961     for (int i = 0; i < 6; i++)
4962     {
4963         memcpy(&data[i * (3 + 4)], &quadVerts[i], sizeof(Vector3));
4964         memcpy(&data[i * (3 + 4) + 3], &kYellow, 4 * sizeof(float));
4965     }
4966 
4967     {
4968         GLBuffer buffer;
4969         glBindBuffer(GL_ARRAY_BUFFER, buffer);
4970         glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(data[0]), data.data(), GL_STATIC_DRAW);
4971 
4972         glEnableVertexAttribArray(posLoc);
4973         glEnableVertexAttribArray(colorLoc);
4974 
4975         glVertexAttribPointer(posLoc, 3, GL_FLOAT, false, 28, reinterpret_cast<void *>(0));
4976         glVertexAttribPointer(colorLoc, 4, GL_FLOAT, false, 28, reinterpret_cast<void *>(12));
4977 
4978         glDrawArrays(GL_TRIANGLES, 0, 6);
4979         EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::yellow);
4980         EXPECT_GL_NO_ERROR();
4981         // Unbind before destroy.
4982         glBindBuffer(GL_ARRAY_BUFFER, 0);
4983     }
4984 
4985     // Modify color to green.
4986     for (int i = 0; i < 6; i++)
4987     {
4988         memcpy(&data[i * (3 + 4) + 3], &kGreen, 4 * sizeof(float));
4989     }
4990 
4991     // Provide client pointer.
4992     glVertexAttribPointer(posLoc, 3, GL_FLOAT, false, 28, data.data());
4993     glVertexAttribPointer(colorLoc, 4, GL_FLOAT, false, 28, &data[3]);
4994 
4995     glDrawArrays(GL_TRIANGLES, 0, 6);
4996     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::green);
4997     EXPECT_GL_NO_ERROR();
4998 }
4999 
5000 // Create a vertex array with an empty array buffer and attribute offsets.
5001 // This succeded in the end2end and capture/replay tests, but resulted in a trace
5002 // producing a GL error when using MEC.
5003 // Validation complained about the following:
5004 // "Client data cannot be used with a non-default vertex array object."
5005 
5006 // To capture this test with MEC run:
5007 // mkdir src/tests/capture_replay_tests/empty_array_buffer_test
5008 // ANGLE_CAPTURE_ENABLED=1 ANGLE_CAPTURE_FRAME_START=2 \
5009 // ANGLE_CAPTURE_FRAME_END=2 ANGLE_CAPTURE_LABEL=empty_array_buffer_test \
5010 // ANGLE_CAPTURE_OUT_DIR=src/tests/capture_replay_tests/empty_array_buffer_test \
5011 // ./out/Debug/angle_end2end_tests \
5012 // --gtest_filter="VertexAttributeTestES3.EmptyArrayBuffer/ES3_Vulkan"
TEST_P(VertexAttributeTestES3,EmptyArrayBuffer)5013 TEST_P(VertexAttributeTestES3, EmptyArrayBuffer)
5014 {
5015     GLVertexArray vertexArray;
5016     glBindVertexArray(vertexArray);
5017 
5018     GLBuffer emptyArrayBuffer;
5019     glBindBuffer(GL_ARRAY_BUFFER, emptyArrayBuffer);
5020 
5021     glEnableVertexAttribArray(0);
5022     glEnableVertexAttribArray(1);
5023     glEnableVertexAttribArray(2);
5024     glVertexAttribPointer(0, 4, GL_UNSIGNED_BYTE, GL_TRUE, 20, reinterpret_cast<const void *>(16));
5025     glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 20, reinterpret_cast<const void *>(8));
5026     glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 20, nullptr);
5027     EXPECT_GL_NO_ERROR();
5028 
5029     glBindBuffer(GL_ARRAY_BUFFER, 0);
5030     glBindVertexArray(0);
5031 
5032     EXPECT_GL_NO_ERROR();
5033 
5034     // Swap a frame for MEC
5035     swapBuffers();
5036 }
5037 
5038 // Set an attrib pointer and delete it's buffer after usage, while keeping the vertex array.
5039 // This will cause MEC to capture an invalid attribute pointer and also trigger
5040 // "Client data cannot be used with a non-default vertex array object."
TEST_P(VertexAttributeTestES3,InvalidAttribPointer)5041 TEST_P(VertexAttributeTestES3, InvalidAttribPointer)
5042 {
5043     GLVertexArray vertexArray;
5044     glBindVertexArray(vertexArray);
5045 
5046     std::array<GLbyte, 12> vertexData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
5047 
5048     {
5049         GLBuffer toBeDeletedArrayBuffer;
5050         glBindBuffer(GL_ARRAY_BUFFER, toBeDeletedArrayBuffer);
5051 
5052         glBufferData(GL_ARRAY_BUFFER, vertexData.size(), vertexData.data(), GL_DYNAMIC_DRAW);
5053 
5054         glEnableVertexAttribArray(0);
5055         glEnableVertexAttribArray(1);
5056 
5057         glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6, nullptr);
5058         glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6, reinterpret_cast<const void *>(6));
5059 
5060         glBindBuffer(GL_ARRAY_BUFFER, 0);
5061         glDisableVertexAttribArray(0);
5062         glDisableVertexAttribArray(1);
5063 
5064         EXPECT_GL_NO_ERROR();
5065     }
5066 
5067     // Set an attrib pointer that will be actually picked up by MEC, since the buffer will be kept.
5068     glEnableVertexAttribArray(0);
5069 
5070     GLBuffer arrayBuffer;
5071     glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
5072 
5073     glBufferData(GL_ARRAY_BUFFER, vertexData.size(), vertexData.data(), GL_DYNAMIC_DRAW);
5074 
5075     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3, reinterpret_cast<const void *>(3));
5076 
5077     EXPECT_GL_NO_ERROR();
5078 
5079     // Swap a frame for MEC
5080     swapBuffers();
5081 
5082     glBindBuffer(GL_ARRAY_BUFFER, 0);
5083     glEnableVertexAttribArray(0);
5084 }
5085 
5086 // Test maxinum attribs full of Client buffers and then switch to mixed.
TEST_P(VertexAttributeTestES3,fullClientBuffersSwitchToMixed)5087 TEST_P(VertexAttributeTestES3, fullClientBuffersSwitchToMixed)
5088 {
5089     GLint maxAttribs;
5090     glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttribs);
5091     ASSERT_GL_NO_ERROR();
5092 
5093     // Reserve one attrib for position
5094     GLint drawAttribs = maxAttribs - 1;
5095 
5096     GLuint program = compileMultiAttribProgram(drawAttribs);
5097     ASSERT_NE(0u, program);
5098 
5099     const std::array<Vector2, 4> kIndexedQuadVertices = {{
5100         Vector2(-1.0f, 1.0f),
5101         Vector2(-1.0f, -1.0f),
5102         Vector2(1.0f, -1.0f),
5103         Vector2(1.0f, 1.0f),
5104     }};
5105 
5106     GLsizei stride = (maxAttribs + 1) * sizeof(GLfloat);
5107 
5108     constexpr std::array<GLushort, 6> kIndexedQuadIndices = {{0, 1, 2, 0, 2, 3}};
5109     GLuint indexBuffer                                    = 0;
5110     glGenBuffers(1, &indexBuffer);
5111 
5112     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
5113     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndexedQuadIndices), kIndexedQuadIndices.data(),
5114                  GL_STATIC_DRAW);
5115 
5116     // Vertex drawAttribs color attributes plus position (x, y).
5117     GLint totalComponents = drawAttribs + 2;
5118     std::vector<GLfloat> vertexData(totalComponents * 4, 0.0f);
5119     for (GLint index = 0; index < 4; ++index)
5120     {
5121         vertexData[index * totalComponents + drawAttribs]     = kIndexedQuadVertices[index].x();
5122         vertexData[index * totalComponents + drawAttribs + 1] = kIndexedQuadVertices[index].y();
5123     }
5124 
5125     GLfloat attributeValue = 0.0f;
5126     GLfloat delta          = 1.0f / 256.0f;
5127     for (GLint attribIndex = 0; attribIndex < drawAttribs; ++attribIndex)
5128     {
5129         vertexData[attribIndex]                       = attributeValue;
5130         vertexData[attribIndex + totalComponents]     = attributeValue;
5131         vertexData[attribIndex + totalComponents * 2] = attributeValue;
5132         vertexData[attribIndex + totalComponents * 3] = attributeValue;
5133         attributeValue += delta;
5134     }
5135 
5136     glUseProgram(program);
5137     for (GLint attribIndex = 0; attribIndex < drawAttribs; ++attribIndex)
5138     {
5139         std::stringstream attribStream;
5140         attribStream << "a" << attribIndex;
5141         GLint location = glGetAttribLocation(program, attribStream.str().c_str());
5142         ASSERT_NE(-1, location);
5143         glVertexAttribPointer(location, 1, GL_FLOAT, GL_FALSE, stride,
5144                               vertexData.data() + attribIndex);
5145         glEnableVertexAttribArray(location);
5146     }
5147     GLint posLoc = glGetAttribLocation(program, "position");
5148     ASSERT_NE(-1, posLoc);
5149     glEnableVertexAttribArray(posLoc);
5150     glVertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, stride, vertexData.data() + drawAttribs);
5151     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
5152 
5153     // the result color should be (0 + 1 + 2 + ... + 14)/256 * 255;
5154     EXPECT_GL_NO_ERROR();
5155     EXPECT_PIXEL_NEAR(0, 0, 105, 0, 0, 255, 1);
5156 
5157     // disable a few attribute use default attribute color
5158     GLint l0  = glGetAttribLocation(program, "a0");
5159     GLint l5  = glGetAttribLocation(program, "a5");
5160     GLint l13 = glGetAttribLocation(program, "a13");
5161     glDisableVertexAttribArray(l0);
5162     glVertexAttrib1f(l0, 1.0f / 16.0f);
5163     glDisableVertexAttribArray(l5);
5164     glVertexAttrib1f(l5, 1.0f / 16.0f);
5165     glDisableVertexAttribArray(l13);
5166     glVertexAttrib1f(l13, 1.0f / 16.0f);
5167 
5168     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
5169 
5170     EXPECT_GL_NO_ERROR();
5171     EXPECT_PIXEL_NEAR(0, 0, 134, 0, 0, 255, 1);
5172 
5173     // disable all the client buffers.
5174     for (GLint attribIndex = 0; attribIndex < drawAttribs; ++attribIndex)
5175     {
5176         std::stringstream attribStream;
5177         attribStream << "a" << attribIndex;
5178         GLint location = glGetAttribLocation(program, attribStream.str().c_str());
5179         ASSERT_NE(-1, location);
5180         glDisableVertexAttribArray(location);
5181         glVertexAttrib1f(location, 1.0f / 16.0f);
5182     }
5183 
5184     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
5185 
5186     EXPECT_GL_NO_ERROR();
5187     EXPECT_PIXEL_NEAR(0, 0, 239, 0, 0, 255, 1);
5188 
5189     // enable all the client buffers.
5190     for (GLint attribIndex = 0; attribIndex < drawAttribs; ++attribIndex)
5191     {
5192         std::stringstream attribStream;
5193         attribStream << "a" << attribIndex;
5194         GLint location = glGetAttribLocation(program, attribStream.str().c_str());
5195         ASSERT_NE(-1, location);
5196         glVertexAttribPointer(location, 1, GL_FLOAT, GL_FALSE, stride,
5197                               vertexData.data() + attribIndex);
5198         glEnableVertexAttribArray(location);
5199     }
5200     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
5201     EXPECT_GL_NO_ERROR();
5202     EXPECT_PIXEL_NEAR(0, 0, 105, 0, 0, 255, 1);
5203 }
5204 
5205 // Test bind an empty buffer for vertex attribute does not crash
TEST_P(VertexAttributeTestES3,emptyBuffer)5206 TEST_P(VertexAttributeTestES3, emptyBuffer)
5207 {
5208     constexpr char vs2[] =
5209         R"(#version 300 es
5210             in uvec4 attr0;
5211             void main()
5212             {
5213                 gl_Position = vec4(attr0.x, 0.0, 0.0, 0.0);
5214             })";
5215     constexpr char fs[] =
5216         R"(#version 300 es
5217             precision highp float;
5218             out vec4 color;
5219             void main()
5220             {
5221                 color = vec4(1.0, 0.0, 0.0, 1.0);
5222             })";
5223     GLuint program2 = CompileProgram(vs2, fs);
5224     GLBuffer buf;
5225     glBindBuffer(GL_ARRAY_BUFFER, buf);
5226     glEnableVertexAttribArray(0);
5227     glVertexAttribIPointer(0, 4, GL_UNSIGNED_BYTE, 0, 0);
5228     glVertexAttribDivisor(0, 2);
5229     glUseProgram(program2);
5230     glDrawArrays(GL_POINTS, 0, 1);
5231 
5232     swapBuffers();
5233 }
5234 
5235 // This is a test for use with ANGLE's Capture/Replay.
5236 // It emulates a situation we see in some apps, where attribs are passed in but may not be used.
5237 // In particular, that test asks for all active attributes and iterates through each one. Before any
5238 // changes to FrameCapture, this will create calls that look up attributes that are considered
5239 // unused on some platforms, making the trace non-portable. Whether they are used depends on how
5240 // well the stack optimizes the shader pipeline. In this instance, we are just passing them across
5241 // the pipeline boundary where they are dead in the fragment shader, but other cases have included
5242 // attributes passed to empty functions, or some eliminated with math. The more optimizations
5243 // applied by the driver, the higher chance of getting an unused attribute.
TEST_P(VertexAttributeTestES3,UnusedAttribsMEC)5244 TEST_P(VertexAttributeTestES3, UnusedAttribsMEC)
5245 {
5246     constexpr char vertexShader[] =
5247         R"(#version 300 es
5248         precision mediump float;
5249         in vec4 position;
5250         in vec4 input_unused;
5251         out vec4 passthrough;
5252         void main()
5253         {
5254             passthrough = input_unused;
5255             gl_Position = position;
5256         })";
5257 
5258     constexpr char fragmentShader[] =
5259         R"(#version 300 es
5260         precision mediump float;
5261         in vec4 passthrough;
5262         out vec4 color;
5263         void main()
5264         {
5265             // ignore passthrough - this makes it unused with cross stage optimizations
5266             color = vec4(1.0);
5267         })";
5268 
5269     GLuint program = CompileProgram(vertexShader, fragmentShader);
5270     glUseProgram(program);
5271 
5272     // Set up vertex data
5273     GLBuffer positionBuffer;
5274     const std::array<Vector3, 6> &quadVerts = GetQuadVertices();
5275     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
5276     glBufferData(GL_ARRAY_BUFFER, quadVerts.size() * sizeof(quadVerts[0]), quadVerts.data(),
5277                  GL_STATIC_DRAW);
5278 
5279     // Loop through a sequence multiple times, so MEC can capture it.
5280     // Ask about vertex attribs and set them up, regardless of whether they are used.
5281     // This matches behavior seen in some apps.
5282     for (int i = 0; i < 10; i++)
5283     {
5284         // Look up the number of attribs
5285         GLint activeAttribCount = 0;
5286         glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &activeAttribCount);
5287 
5288         // Look up how big they might get
5289         GLint maxActiveAttribLength = 0;
5290         glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxActiveAttribLength);
5291 
5292         GLsizei attribLength  = 0;
5293         GLint attribSize      = 0;
5294         GLenum attribType     = 0;
5295         GLchar attribName[16] = {0};
5296         ASSERT(maxActiveAttribLength < 16);
5297 
5298         // Look up each attribute and set them up
5299         for (int j = 0; j < activeAttribCount; j++)
5300         {
5301             glGetActiveAttrib(program, j, maxActiveAttribLength, &attribLength, &attribSize,
5302                               &attribType, attribName);
5303             GLint posLoc = glGetAttribLocation(program, attribName);
5304             ASSERT_NE(posLoc, -1);
5305             glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, j, nullptr);
5306             glEnableVertexAttribArray(posLoc);
5307         }
5308 
5309         // Draw and swap on each loop to trigger MEC
5310         glDrawArrays(GL_TRIANGLES, 0, 6);
5311         EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::white);
5312         swapBuffers();
5313     }
5314 }
5315 
5316 // Test that a particular vertex attribute naming does not affect the functionality.
5317 // Tests the vertex attrib aliasing part. Note that aliasing works with es 100 shaders.
TEST_P(VertexAttributeTest,AliasingAttribNaming)5318 TEST_P(VertexAttributeTest, AliasingAttribNaming)
5319 {
5320     // http://anglebug.com/42263740
5321     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
5322 
5323     // http://anglebug.com/42262130
5324     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
5325 
5326     // http://anglebug.com/42262131
5327     ANGLE_SKIP_TEST_IF(IsD3D());
5328 
5329     // This test needs 16 total attributes. All backends support this except some old Android
5330     // devices.
5331     GLint maxVertexAttribs = 0;
5332     glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
5333     ANGLE_SKIP_TEST_IF(maxVertexAttribs < 16);
5334 
5335     constexpr char kVS[] = R"(attribute vec4 position;
5336 // attributes aliasing location 0 and above
5337 attribute mat3 a;
5338 attribute mat2 a_;
5339 
5340 // attributes aliasing location 1 and above
5341 attribute vec4 a_1;
5342 
5343 // attributes aliasing location 2 and above
5344 attribute mat4 a_0;
5345 
5346 // In summary:
5347 //
5348 // location 0: a[0] a_[0]
5349 // location 1: a[1] a_[1] a_1
5350 // location 2: a[2]          a_0[0]
5351 // location 3:               a_0[1] (untested)
5352 // location 4:               a_0[2] (untested)
5353 // location 5:               a_0[3] (untested)
5354 
5355 const vec3 loc0Expected = vec3(0.05, 0.1, 0.15);
5356 const vec4 loc1Expected = vec4(0.2, 0.25, 0.3, 0.35);
5357 const vec4 loc2Expected = vec4(0.4, 0.45, 0.5, 0.55);
5358 
5359 uniform float loc0Select;
5360 uniform float loc1Select;
5361 uniform float loc2Select;
5362 
5363 // Each channel controlled by success from each set of aliasing locations.  If a channel is 0,
5364 // the attribute test has failed.  Otherwise it will be 1/N, 2/N, ..., 1, depending on how many
5365 // possible values there are for the controlling uniforms.
5366 varying mediump vec4 color;
5367 void main()
5368 {
5369     gl_Position = position;
5370 
5371     vec4 result = vec4(0);
5372 
5373     if (loc0Select < 0.5)
5374         result.r = all(lessThan(abs(a[0] - loc0Expected.xyz), vec3(0.01))) ? 0.5 : 0.0;
5375     else
5376         result.r = all(lessThan(abs(a_[0] - loc0Expected.xy), vec2(0.01))) ? 1.0 : 0.0;
5377 
5378     if (loc1Select < 0.5)
5379         result.g = all(lessThan(abs(a[1] - loc1Expected.xyz), vec3(0.01))) ? 0.333333 : 0.0;
5380     else if (loc1Select < 1.5)
5381         result.g = all(lessThan(abs(a_[1] - loc1Expected.xy), vec2(0.01))) ? 0.666667 : 0.0;
5382     else
5383         result.g = all(lessThan(abs(a_1 - loc1Expected), vec4(0.01))) ? 1.0 : 0.0;
5384 
5385     if (loc2Select < 0.5)
5386         result.b = all(lessThan(abs(a[2] - loc2Expected.xyz), vec3(0.01))) ? 0.5 : 0.0;
5387     else
5388         result.b = all(lessThan(abs(a_0[0] - loc2Expected), vec4(0.01))) ? 1.0 : 0.0;
5389     result.a = 1.0;
5390     color = result;
5391 })";
5392 
5393     constexpr char kFS[] = R"(varying mediump vec4 color;
5394     void main(void)
5395     {
5396         gl_FragColor = color;
5397     })";
5398 
5399     // Compile shaders.
5400     GLuint program = CompileProgram(kVS, kFS);
5401     ASSERT_NE(program, 0u);
5402 
5403     // Setup bindings.
5404     glBindAttribLocation(program, 0, "a");
5405     glBindAttribLocation(program, 0, "a_");
5406     glBindAttribLocation(program, 1, "a_1");
5407     glBindAttribLocation(program, 2, "a_0");
5408     EXPECT_GL_NO_ERROR();
5409 
5410     // Link program and get uniform locations.
5411     glLinkProgram(program);
5412     glUseProgram(program);
5413     EXPECT_GL_NO_ERROR();
5414 
5415     GLint loc0SelectLoc = glGetUniformLocation(program, "loc0Select");
5416     GLint loc1SelectLoc = glGetUniformLocation(program, "loc1Select");
5417     GLint loc2SelectLoc = glGetUniformLocation(program, "loc2Select");
5418     ASSERT_NE(-1, loc0SelectLoc);
5419     ASSERT_NE(-1, loc1SelectLoc);
5420     ASSERT_NE(-1, loc2SelectLoc);
5421     EXPECT_GL_NO_ERROR();
5422 
5423     // Set values for attributes.
5424     glVertexAttrib3f(0, 0.05, 0.1, 0.15);
5425     glVertexAttrib4f(1, 0.2, 0.25, 0.3, 0.35);
5426     glVertexAttrib4f(2, 0.4, 0.45, 0.5, 0.55);
5427     glDisableVertexAttribArray(0);
5428     glDisableVertexAttribArray(1);
5429     glDisableVertexAttribArray(2);
5430     EXPECT_GL_NO_ERROR();
5431 
5432     // Go through different combination of attributes and make sure reading through every alias is
5433     // correctly handled.
5434     GLColor expected;
5435     expected.A = 255;
5436     for (uint32_t loc0Select = 0; loc0Select < 2; ++loc0Select)
5437     {
5438         glUniform1f(loc0SelectLoc, loc0Select);
5439         expected.R = loc0Select * 127 + 127;
5440 
5441         for (uint32_t loc1Select = 0; loc1Select < 3; ++loc1Select)
5442         {
5443             glUniform1f(loc1SelectLoc, loc1Select);
5444             expected.G = loc1Select * 85 + 85;
5445 
5446             for (uint32_t loc2Select = 0; loc2Select < 2; ++loc2Select)
5447             {
5448                 glUniform1f(loc2SelectLoc, loc2Select);
5449                 expected.B = loc2Select * 127 + 127;
5450                 drawQuad(program, "position", 0.5f);
5451                 EXPECT_GL_NO_ERROR();
5452                 EXPECT_PIXEL_COLOR_NEAR(0, 0, expected, 1);
5453             }
5454         }
5455     }
5456 }
5457 
5458 // Test that a particular vertex attribute naming does not affect the functionality.
TEST_P(VertexAttributeTestES3,AttribNaming)5459 TEST_P(VertexAttributeTestES3, AttribNaming)
5460 {
5461     // http://anglebug.com/42263740
5462     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
5463 
5464     // http://anglebug.com/42262130
5465     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
5466 
5467     // http://anglebug.com/42262131
5468     ANGLE_SKIP_TEST_IF(IsD3D());
5469 
5470     // This test needs roughly 16 total attributes. All backends support this except some old
5471     // Android devices.
5472     GLint maxVertexAttribs = 0;
5473     glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
5474     ANGLE_SKIP_TEST_IF(maxVertexAttribs < 16);
5475 
5476     constexpr char kVS[] = R"(#version 300 es
5477 precision mediump float;
5478 in vec4 position;
5479 in mat3 a;
5480 in mat2 a_;
5481 in vec4 a_1;
5482 in vec4 a_0;
5483 const mat3 aExpected = mat3(0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8);
5484 const mat2 a_Expected = mat2(1.0, 1.1, 1.2, 1.3);
5485 const vec4 a_1Expected = vec4(2.0, 2.1, 2.2, 2.3);
5486 const vec4 a_0Expected = vec4(3.0, 3.1, 3.2, 3.3);
5487 out mediump vec4 color;
5488 void main()
5489 {
5490     gl_Position = position;
5491 
5492     vec4 result = vec4(0);
5493     mat3 diff3 = a - aExpected;
5494     result.r = all(lessThan(abs(diff3[0]) + abs(diff3[1]) + abs(diff3[2]), vec3(0.01))) ? 1.0 : 0.0;
5495     mat2 diff2 = a_ - a_Expected;
5496     result.g = all(lessThan(abs(diff2[0]) + abs(diff2[1]), vec2(0.01))) ? 1.0 : 0.0;
5497     result.b = all(lessThan(abs(a_1 - a_1Expected), vec4(0.01))) ? 1.0 : 0.0;
5498     result.a = all(lessThan(abs(a_0 - a_0Expected), vec4(0.01))) ? 1.0 : 0.0;
5499     color = result;
5500 })";
5501 
5502     constexpr char kFS[] = R"(#version 300 es
5503 in mediump vec4 color;
5504 out mediump vec4 fragColor;
5505 void main(void)
5506 {
5507     fragColor = color;
5508 })";
5509 
5510     GLuint program = CompileProgram(kVS, kFS);
5511     ASSERT_NE(program, 0u);
5512 
5513     glBindAttribLocation(program, 0, "a");
5514     glBindAttribLocation(program, 4, "a_");
5515     glBindAttribLocation(program, 6, "a_1");
5516     glBindAttribLocation(program, 7, "a_0");
5517     EXPECT_GL_NO_ERROR();
5518 
5519     glLinkProgram(program);
5520     glUseProgram(program);
5521     EXPECT_GL_NO_ERROR();
5522 
5523     // Set values for attributes.
5524     glVertexAttrib3f(0, 0.0, 0.1, 0.2);
5525     glVertexAttrib3f(1, 0.3, 0.4, 0.5);
5526     glVertexAttrib3f(2, 0.6, 0.7, 0.8);
5527     glVertexAttrib2f(4, 1.0, 1.1);
5528     glVertexAttrib2f(5, 1.2, 1.3);
5529     glVertexAttrib4f(6, 2.0, 2.1, 2.2, 2.3);
5530     glVertexAttrib4f(7, 3.0, 3.1, 3.2, 3.3);
5531 
5532     glDisableVertexAttribArray(0);
5533     glDisableVertexAttribArray(1);
5534     glDisableVertexAttribArray(2);
5535     glDisableVertexAttribArray(3);
5536     glDisableVertexAttribArray(4);
5537     glDisableVertexAttribArray(5);
5538     glDisableVertexAttribArray(6);
5539     glDisableVertexAttribArray(7);
5540     glDisableVertexAttribArray(8);
5541     glDisableVertexAttribArray(9);
5542     EXPECT_GL_NO_ERROR();
5543 
5544     // Go through different combination of attributes and make sure reading through every alias is
5545     // correctly handled.
5546     GLColor expected{255, 255, 255, 255};
5547     drawQuad(program, "position", 0.5f);
5548     EXPECT_GL_NO_ERROR();
5549     EXPECT_PIXEL_COLOR_NEAR(0, 0, expected, 1);
5550 }
5551 
5552 // VAO emulation fails on Mac but is not used on Mac in the wild. http://anglebug.com/40096758
5553 #if !defined(__APPLE__)
5554 #    define EMULATED_VAO_CONFIGS                                          \
5555         ES2_OPENGL().enable(Feature::SyncAllVertexArraysToDefault),       \
5556             ES2_OPENGLES().enable(Feature::SyncAllVertexArraysToDefault), \
5557             ES3_OPENGL().enable(Feature::SyncAllVertexArraysToDefault),   \
5558             ES3_OPENGLES().enable(Feature::SyncAllVertexArraysToDefault),
5559 #else
5560 #    define EMULATED_VAO_CONFIGS
5561 #endif
5562 
5563 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(
5564     VertexAttributeTest,
5565     ES2_VULKAN().enable(Feature::ForceFallbackFormat),
5566     ES2_VULKAN_SWIFTSHADER().enable(Feature::ForceFallbackFormat),
5567     ES3_VULKAN().enable(Feature::ForceFallbackFormat),
5568     ES3_VULKAN_SWIFTSHADER().enable(Feature::ForceFallbackFormat),
5569     ES3_METAL().disable(Feature::HasExplicitMemBarrier).disable(Feature::HasCheapRenderPass),
5570     ES3_METAL().disable(Feature::HasExplicitMemBarrier).enable(Feature::HasCheapRenderPass),
5571     ES2_OPENGL().enable(Feature::ForceMinimumMaxVertexAttributes),
5572     ES2_OPENGLES().enable(Feature::ForceMinimumMaxVertexAttributes),
5573     EMULATED_VAO_CONFIGS);
5574 
5575 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(
5576     VertexAttributeOORTest,
5577     ES2_VULKAN().enable(Feature::ForceFallbackFormat),
5578     ES2_VULKAN_SWIFTSHADER().enable(Feature::ForceFallbackFormat),
5579     ES3_VULKAN().enable(Feature::ForceFallbackFormat),
5580     ES3_VULKAN_SWIFTSHADER().enable(Feature::ForceFallbackFormat),
5581     ES3_METAL().disable(Feature::HasExplicitMemBarrier).disable(Feature::HasCheapRenderPass),
5582     ES3_METAL().disable(Feature::HasExplicitMemBarrier).enable(Feature::HasCheapRenderPass));
5583 
5584 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(RobustVertexAttributeTest);
5585 
5586 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VertexAttributeTestES3);
5587 ANGLE_INSTANTIATE_TEST_ES3_AND(
5588     VertexAttributeTestES3,
5589     ES3_VULKAN().enable(Feature::ForceFallbackFormat),
5590     ES3_VULKAN_SWIFTSHADER().enable(Feature::ForceFallbackFormat),
5591     ES3_METAL().disable(Feature::HasExplicitMemBarrier).disable(Feature::HasCheapRenderPass),
5592     ES3_METAL().disable(Feature::HasExplicitMemBarrier).enable(Feature::HasCheapRenderPass),
5593     ES3_VULKAN()
5594         .disable(Feature::UseVertexInputBindingStrideDynamicState)
5595         .disable(Feature::SupportsGraphicsPipelineLibrary));
5596 
5597 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VertexAttributeTestES31);
5598 ANGLE_INSTANTIATE_TEST_ES31_AND(VertexAttributeTestES31,
5599                                 ES31_VULKAN().enable(Feature::ForceFallbackFormat),
5600                                 ES31_VULKAN_SWIFTSHADER().enable(Feature::ForceFallbackFormat),
5601                                 ES31_VULKAN()
5602                                     .disable(Feature::UseVertexInputBindingStrideDynamicState)
5603                                     .disable(Feature::SupportsGraphicsPipelineLibrary));
5604 
5605 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(
5606     VertexAttributeCachingTest,
5607     ES2_VULKAN().enable(Feature::ForceFallbackFormat),
5608     ES2_VULKAN_SWIFTSHADER().enable(Feature::ForceFallbackFormat),
5609     ES3_VULKAN().enable(Feature::ForceFallbackFormat),
5610     ES3_VULKAN_SWIFTSHADER().enable(Feature::ForceFallbackFormat),
5611     ES3_METAL().disable(Feature::HasExplicitMemBarrier).disable(Feature::HasCheapRenderPass),
5612     ES3_METAL().disable(Feature::HasExplicitMemBarrier).enable(Feature::HasCheapRenderPass));
5613 
5614 }  // anonymous namespace
5615