• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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__anonaec9f1eb0111::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/5399
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 // Tests that we do not generate a SIGBUS error on arm when translating unaligned data.
2011 // GL_RG32_SNORM_ANGLEX is used when using glVertexAttribPointer with certain parameters.
TEST_P(VertexAttributeTestES3,DrawWithUnalignedData)2012 TEST_P(VertexAttributeTestES3, DrawWithUnalignedData)
2013 {
2014     constexpr char kVS[] = R"(#version 300 es
2015 precision highp float;
2016 in highp vec4 a_position;
2017 in highp vec2 a_ColorTest;
2018 out highp vec2 v_colorTest;
2019 
2020 void main() {
2021     v_colorTest = a_ColorTest;
2022     gl_Position = a_position;
2023 })";
2024 
2025     constexpr char kFS[] = R"(#version 300 es
2026 precision highp float;
2027 in highp vec2 v_colorTest;
2028 out vec4 fragColor;
2029 
2030 void main() {
2031     // The input value is 0x01000000 / 0x7FFFFFFF
2032     if(abs(v_colorTest.x - 0.0078125) < 0.001) {
2033         fragColor = vec4(0.0, 1.0, 0.0, 1.0);
2034     } else {
2035         fragColor = vec4(1.0, 0.0, 0.0, 1.0);
2036     }
2037 })";
2038 
2039     ANGLE_GL_PROGRAM(program, kVS, kFS);
2040     glBindAttribLocation(program, 0, "a_position");
2041     glBindAttribLocation(program, 1, "a_ColorTest");
2042     glLinkProgram(program);
2043     glUseProgram(program);
2044     ASSERT_GL_NO_ERROR();
2045 
2046     constexpr size_t kDataSize = 12;
2047 
2048     // Initialize vertex attribute data with 1u32s, but shifted right by a variable number of bytes
2049     GLubyte colorTestData[(kDataSize + 1) * sizeof(GLuint)];
2050 
2051     for (size_t offset = 0; offset < sizeof(GLuint); offset++)
2052     {
2053         for (size_t dataIndex = 0; dataIndex < kDataSize * sizeof(GLuint); dataIndex++)
2054         {
2055             if (dataIndex % sizeof(GLuint) == sizeof(GLuint) - 1)
2056             {
2057                 colorTestData[dataIndex + offset] = 1;
2058             }
2059             else
2060             {
2061 
2062                 colorTestData[dataIndex + offset] = 0;
2063             }
2064         }
2065 
2066         GLubyte *offsetPtr = &colorTestData[offset];
2067         glVertexAttribPointer(1, 2, GL_INT, GL_TRUE, sizeof(GLuint), offsetPtr);
2068 
2069         glBindBuffer(GL_ARRAY_BUFFER, 0);
2070         glEnableVertexAttribArray(1);
2071 
2072         drawIndexedQuad(program, "a_position", 0.5f, 1.0f, false, true);
2073 
2074         // Verify green was drawn.
2075         EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
2076         ASSERT_GL_NO_ERROR();
2077     }
2078 }
2079 
2080 // Tests that rendering is fine if GL_ANGLE_relaxed_vertex_attribute_type is enabled
2081 // and mismatched integer signedness between the program's attribute type and the
2082 // attribute type specified by VertexAttribIPointer are used.
TEST_P(VertexAttributeTestES3,DrawWithRelaxedVertexAttributeType)2083 TEST_P(VertexAttributeTestES3, DrawWithRelaxedVertexAttributeType)
2084 {
2085     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_relaxed_vertex_attribute_type"));
2086 
2087     constexpr char kVS[] = R"(#version 300 es
2088 precision highp float;
2089 in highp vec4 a_position;
2090 in highp ivec4 a_ColorTest;
2091 out highp vec4 v_colorTest;
2092 
2093 void main() {
2094     v_colorTest = vec4(a_ColorTest);
2095     gl_Position = a_position;
2096 })";
2097 
2098     constexpr char kFS[] = R"(#version 300 es
2099 precision highp float;
2100 in highp vec4 v_colorTest;
2101 out vec4 fragColor;
2102 
2103 void main() {
2104     if(v_colorTest.x > 0.5) {
2105         fragColor = vec4(0.0, 1.0, 0.0, 1.0);
2106     } else {
2107         fragColor = vec4(1.0, 0.0, 0.0, 1.0);
2108     }
2109 })";
2110 
2111     ANGLE_GL_PROGRAM(program, kVS, kFS);
2112     glBindAttribLocation(program, 0, "a_position");
2113     glBindAttribLocation(program, 1, "a_ColorTest");
2114     glLinkProgram(program);
2115     glUseProgram(program);
2116     ASSERT_GL_NO_ERROR();
2117 
2118     constexpr size_t kDataSize = 48;
2119 
2120     // Interleave test data with 0's.
2121     // This guards against a future code change that adjusts stride to 0
2122 
2123     // clang-format off
2124     constexpr GLuint kColorTestData[kDataSize] = {
2125         // Vertex attribute data      Unused data
2126         0u, 0u, 0u, 0u, /*red*/       0u, 0u, 0u, 0u,
2127         1u, 1u, 1u, 1u,               0u, 0u, 0u, 0u,
2128         1u, 1u, 1u, 1u,               0u, 0u, 0u, 0u,
2129         1u, 1u, 1u, 1u,               0u, 0u, 0u, 0u,
2130         1u, 1u, 1u, 1u,               0u, 0u, 0u, 0u,
2131         1u, 1u, 1u, 1u,               0u, 0u, 0u, 0u
2132     };
2133     // clang-format on
2134 
2135     GLBuffer buffer;
2136     glBindBuffer(GL_ARRAY_BUFFER, buffer);
2137     glBufferData(GL_ARRAY_BUFFER, sizeof(GLuint) * kDataSize, kColorTestData, GL_STATIC_DRAW);
2138 
2139     glVertexAttribIPointer(1, 4, GL_UNSIGNED_INT, 8 * sizeof(GLuint),
2140                            reinterpret_cast<const void *>(0));
2141 
2142     glBindBuffer(GL_ARRAY_BUFFER, 0);
2143     glEnableVertexAttribArray(1);
2144 
2145     drawQuad(program, "a_position", 0.5f);
2146 
2147     // Verify green was drawn. If the stride isn't adjusted to 0 this corner will be green. If it is
2148     // adjusted to 0, the whole image will be red
2149     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
2150     ASSERT_GL_NO_ERROR();
2151 }
2152 
2153 // Test that ensures we do not send data for components not specified by glVertexAttribPointer when
2154 // component types and sizes are mismatched
TEST_P(VertexAttributeTestES3,DrawWithMismatchedComponentCount)2155 TEST_P(VertexAttributeTestES3, DrawWithMismatchedComponentCount)
2156 {
2157     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_relaxed_vertex_attribute_type"));
2158 
2159     // To ensure the test results are valid when we don't send data for every component, the
2160     // shader's values must be defined by the backend.
2161     // Vulkan Spec 22.3. Vertex Attribute Divisor in Instanced Rendering
2162     // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#_vertex_attribute_divisor_in_instanced_rendering
2163     // If the format does not include G, B, or A components, then those are filled with (0,0,1) as
2164     // needed (using either 1.0f or integer 1 based on the format) for attributes that are not
2165     // 64-bit data types.
2166     ANGLE_SKIP_TEST_IF(!IsVulkan());
2167 
2168     constexpr char kVS[] = R"(#version 300 es
2169 precision highp float;
2170 in highp vec4 a_position;
2171 in highp ivec2 a_ColorTest;
2172 out highp vec2 v_colorTest;
2173 
2174 void main() {
2175     v_colorTest = vec2(a_ColorTest);
2176     gl_Position = a_position;
2177 })";
2178 
2179     constexpr char kFS[] = R"(#version 300 es
2180 precision highp float;
2181 in highp vec2 v_colorTest;
2182 out vec4 fragColor;
2183 
2184 void main() {
2185     if(v_colorTest.y < 0.5) {
2186         fragColor = vec4(0.0, 1.0, 0.0, 1.0);
2187     } else {
2188         fragColor = vec4(1.0, 0.0, 0.0, 1.0);
2189     }
2190 })";
2191 
2192     ANGLE_GL_PROGRAM(program, kVS, kFS);
2193     glBindAttribLocation(program, 0, "a_position");
2194     glBindAttribLocation(program, 1, "a_ColorTest");
2195     glLinkProgram(program);
2196     glUseProgram(program);
2197     ASSERT_GL_NO_ERROR();
2198 
2199     constexpr size_t kDataSize = 24;
2200 
2201     // Initialize vertex attribute data with 1s.
2202     GLuint kColorTestData[kDataSize];
2203     for (size_t dataIndex = 0; dataIndex < kDataSize; dataIndex++)
2204     {
2205         kColorTestData[dataIndex] = 1u;
2206     }
2207 
2208     GLBuffer buffer;
2209     glBindBuffer(GL_ARRAY_BUFFER, buffer);
2210     glBufferData(GL_ARRAY_BUFFER, sizeof(GLuint) * kDataSize, kColorTestData, GL_STATIC_DRAW);
2211 
2212     glVertexAttribIPointer(1, 1, GL_UNSIGNED_INT, 4 * sizeof(GLuint),
2213                            reinterpret_cast<const void *>(0));
2214 
2215     glBindBuffer(GL_ARRAY_BUFFER, 0);
2216     glEnableVertexAttribArray(1);
2217 
2218     drawQuad(program, "a_position", 0.5f);
2219 
2220     // Verify green was drawn.
2221     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::green);
2222     ASSERT_GL_NO_ERROR();
2223 }
2224 
2225 // Test that ensures we do not send data for components not specified by glVertexAttribPointer when
2226 // component types and sizes are mismatched. Also guard against out of bound errors when atttribute
2227 // locations are specified.
TEST_P(VertexAttributeTestES3,DrawWithMismatchedComponentCountLocationSpecified)2228 TEST_P(VertexAttributeTestES3, DrawWithMismatchedComponentCountLocationSpecified)
2229 {
2230     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_relaxed_vertex_attribute_type"));
2231 
2232     // To ensure the test results are valid when we don't send data for every component, the
2233     // shader's values must be defined by the backend.
2234     // Vulkan Spec 22.3. Vertex Attribute Divisor in Instanced Rendering
2235     // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#_vertex_attribute_divisor_in_instanced_rendering
2236     // If the format does not include G, B, or A components, then those are filled with (0,0,1) as
2237     // needed (using either 1.0f or integer 1 based on the format) for attributes that are not
2238     // 64-bit data types.
2239     ANGLE_SKIP_TEST_IF(!IsVulkan());
2240 
2241     constexpr char kVS[] = R"(#version 300 es
2242 precision highp float;
2243 layout(location = 2) in highp vec4 a_position;
2244 layout(location = 0) in highp ivec2 a_ColorTest;
2245 out highp vec2 v_colorTest;
2246 
2247 void main() {
2248     v_colorTest = vec2(a_ColorTest);
2249     gl_Position = a_position;
2250 })";
2251 
2252     constexpr char kFS[] = R"(#version 300 es
2253 precision highp float;
2254 in highp vec2 v_colorTest;
2255 out vec4 fragColor;
2256 
2257 void main() {
2258     if(v_colorTest.y < 0.5) {
2259         fragColor = vec4(0.0, 1.0, 0.0, 1.0);
2260     } else {
2261         fragColor = vec4(1.0, 0.0, 0.0, 1.0);
2262     }
2263 })";
2264 
2265     ANGLE_GL_PROGRAM(program, kVS, kFS);
2266     glLinkProgram(program);
2267     glUseProgram(program);
2268     ASSERT_GL_NO_ERROR();
2269 
2270     constexpr size_t kDataSize = 24;
2271 
2272     // Initialize vertex attribute data with 1s.
2273     GLuint kColorTestData[kDataSize];
2274     for (size_t dataIndex = 0; dataIndex < kDataSize; dataIndex++)
2275     {
2276         kColorTestData[dataIndex] = 1u;
2277     }
2278 
2279     GLBuffer buffer;
2280     glBindBuffer(GL_ARRAY_BUFFER, buffer);
2281     glBufferData(GL_ARRAY_BUFFER, sizeof(GLuint) * kDataSize, kColorTestData, GL_STATIC_DRAW);
2282 
2283     GLint colorLocation = glGetAttribLocation(program, "a_ColorTest");
2284     ASSERT_NE(colorLocation, -1);
2285     glVertexAttribIPointer(colorLocation, 1, GL_UNSIGNED_INT, 4 * sizeof(GLuint),
2286                            reinterpret_cast<const void *>(0));
2287 
2288     glBindBuffer(GL_ARRAY_BUFFER, 0);
2289     glEnableVertexAttribArray(1);
2290 
2291     drawQuad(program, "a_position", 0.5f);
2292 
2293     // Verify green was drawn.
2294     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::green);
2295     ASSERT_GL_NO_ERROR();
2296 }
2297 
2298 class VertexAttributeTestES31 : public VertexAttributeTestES3
2299 {
2300   protected:
VertexAttributeTestES31()2301     VertexAttributeTestES31() {}
2302 
initTest()2303     void initTest()
2304     {
2305         initBasicProgram();
2306         glUseProgram(mProgram);
2307 
2308         glGenVertexArrays(1, &mVAO);
2309         glBindVertexArray(mVAO);
2310 
2311         auto quadVertices = GetQuadVertices();
2312         GLsizeiptr quadVerticesSize =
2313             static_cast<GLsizeiptr>(quadVertices.size() * sizeof(quadVertices[0]));
2314         glGenBuffers(1, &mQuadBuffer);
2315         glBindBuffer(GL_ARRAY_BUFFER, mQuadBuffer);
2316         glBufferData(GL_ARRAY_BUFFER, quadVerticesSize, quadVertices.data(), GL_STATIC_DRAW);
2317 
2318         GLint positionLocation = glGetAttribLocation(mProgram, "position");
2319         ASSERT_NE(-1, positionLocation);
2320         glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2321         glEnableVertexAttribArray(positionLocation);
2322 
2323         std::array<GLfloat, kVertexCount> expectedData;
2324         for (size_t count = 0; count < kVertexCount; ++count)
2325         {
2326             expectedData[count] = static_cast<GLfloat>(count);
2327         }
2328 
2329         const GLsizei kExpectedDataSize = kVertexCount * kFloatStride;
2330         glGenBuffers(1, &mExpectedBuffer);
2331         glBindBuffer(GL_ARRAY_BUFFER, mExpectedBuffer);
2332         glBufferData(GL_ARRAY_BUFFER, kExpectedDataSize, expectedData.data(), GL_STATIC_DRAW);
2333         glVertexAttribPointer(mExpectedAttrib, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
2334         glEnableVertexAttribArray(mExpectedAttrib);
2335     }
2336 
testTearDown()2337     void testTearDown() override
2338     {
2339         VertexAttributeTestES3::testTearDown();
2340 
2341         glDeleteBuffers(1, &mQuadBuffer);
2342         glDeleteBuffers(1, &mExpectedBuffer);
2343         glDeleteVertexArrays(1, &mVAO);
2344     }
2345 
drawArraysWithStrideAndRelativeOffset(GLint stride,GLuint relativeOffset)2346     void drawArraysWithStrideAndRelativeOffset(GLint stride, GLuint relativeOffset)
2347     {
2348         initTest();
2349 
2350         GLint floatStride          = std::max(stride / kFloatStride, 1);
2351         GLuint floatRelativeOffset = relativeOffset / kFloatStride;
2352         size_t floatCount = static_cast<size_t>(floatRelativeOffset) + kVertexCount * floatStride;
2353         GLsizeiptr inputSize = static_cast<GLsizeiptr>(floatCount) * kFloatStride;
2354 
2355         std::vector<GLfloat> inputData(floatCount);
2356         for (size_t count = 0; count < kVertexCount; ++count)
2357         {
2358             inputData[floatRelativeOffset + count * floatStride] = static_cast<GLfloat>(count);
2359         }
2360 
2361         // Ensure inputSize, inputStride and inputOffset are multiples of TypeStride(GL_FLOAT).
2362         GLsizei inputStride            = floatStride * kFloatStride;
2363         GLsizeiptr inputRelativeOffset = floatRelativeOffset * kFloatStride;
2364         glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
2365         glBufferData(GL_ARRAY_BUFFER, inputSize, nullptr, GL_STATIC_DRAW);
2366         glBufferSubData(GL_ARRAY_BUFFER, 0, inputSize, inputData.data());
2367         glVertexAttribFormat(mTestAttrib, 1, GL_FLOAT, GL_FALSE,
2368                              base::checked_cast<GLuint>(inputRelativeOffset));
2369         glBindVertexBuffer(mTestAttrib, mBuffer, 0, inputStride);
2370         glEnableVertexAttribArray(mTestAttrib);
2371 
2372         glDrawArrays(GL_TRIANGLES, 0, 6);
2373         checkPixels();
2374 
2375         EXPECT_GL_NO_ERROR();
2376     }
2377 
initOnlyUpdateBindingTest(GLint bindingToUpdate)2378     void initOnlyUpdateBindingTest(GLint bindingToUpdate)
2379     {
2380         initTest();
2381 
2382         constexpr GLuint kTestFloatOffset1                               = kVertexCount;
2383         std::array<GLfloat, kTestFloatOffset1 + kVertexCount> inputData1 = {};
2384         for (size_t count = 0; count < kVertexCount; ++count)
2385         {
2386             GLfloat value                         = static_cast<GLfloat>(count);
2387             inputData1[kTestFloatOffset1 + count] = value;
2388         }
2389 
2390         GLBuffer testBuffer1;
2391         glBindBuffer(GL_ARRAY_BUFFER, testBuffer1);
2392         glBufferData(GL_ARRAY_BUFFER, inputData1.size() * kFloatStride, inputData1.data(),
2393                      GL_STATIC_DRAW);
2394 
2395         ASSERT_NE(bindingToUpdate, mTestAttrib);
2396         ASSERT_NE(bindingToUpdate, mExpectedAttrib);
2397 
2398         // Set mTestAttrib using the binding bindingToUpdate.
2399         glVertexAttribFormat(mTestAttrib, 1, GL_FLOAT, GL_FALSE, 0);
2400         glBindVertexBuffer(bindingToUpdate, testBuffer1, kTestFloatOffset1 * kFloatStride,
2401                            kFloatStride);
2402         glVertexAttribBinding(mTestAttrib, bindingToUpdate);
2403         glEnableVertexAttribArray(mTestAttrib);
2404 
2405         // In the first draw the current VAO states are set to driver.
2406         glDrawArrays(GL_TRIANGLES, 0, 6);
2407         checkPixels();
2408         EXPECT_GL_NO_ERROR();
2409 
2410         // We need the second draw to ensure all VAO dirty bits are reset.
2411         // e.g. On D3D11 back-ends, Buffer11::resize is called in the first draw, where the related
2412         // binding is set to dirty again.
2413         glDrawArrays(GL_TRIANGLES, 0, 6);
2414         checkPixels();
2415         EXPECT_GL_NO_ERROR();
2416     }
2417 
2418     std::string makeMismatchingSignsTestVS(uint32_t attribCount, uint16_t signedMask);
2419     std::string makeMismatchingSignsTestFS(uint32_t attribCount);
2420     uint16_t setupVertexAttribPointersForMismatchSignsTest(uint16_t currentSignedMask,
2421                                                            uint16_t toggleMask);
2422 
2423     GLuint mVAO            = 0;
2424     GLuint mExpectedBuffer = 0;
2425     GLuint mQuadBuffer     = 0;
2426 
2427     const GLsizei kFloatStride = TypeStride(GL_FLOAT);
2428 
2429     // Set the maximum value for stride and relativeOffset in case they are too large.
2430     const GLint MAX_STRIDE_FOR_TEST          = 4095;
2431     const GLint MAX_RELATIVE_OFFSET_FOR_TEST = 4095;
2432 };
2433 
2434 // Verify that MAX_VERTEX_ATTRIB_STRIDE is no less than the minimum required value (2048) in ES3.1.
TEST_P(VertexAttributeTestES31,MaxVertexAttribStride)2435 TEST_P(VertexAttributeTestES31, MaxVertexAttribStride)
2436 {
2437     GLint maxStride;
2438     glGetIntegerv(GL_MAX_VERTEX_ATTRIB_STRIDE, &maxStride);
2439     ASSERT_GL_NO_ERROR();
2440 
2441     EXPECT_GE(maxStride, 2048);
2442 }
2443 
2444 // Verify that GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET is no less than the minimum required value
2445 // (2047) in ES3.1.
TEST_P(VertexAttributeTestES31,MaxVertexAttribRelativeOffset)2446 TEST_P(VertexAttributeTestES31, MaxVertexAttribRelativeOffset)
2447 {
2448     GLint maxRelativeOffset;
2449     glGetIntegerv(GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET, &maxRelativeOffset);
2450     ASSERT_GL_NO_ERROR();
2451 
2452     EXPECT_GE(maxRelativeOffset, 2047);
2453 }
2454 
2455 // Verify using MAX_VERTEX_ATTRIB_STRIDE as stride doesn't mess up the draw.
2456 // Use default value if the value of MAX_VERTEX_ATTRIB_STRIDE is too large for this test.
TEST_P(VertexAttributeTestES31,DrawArraysWithLargeStride)2457 TEST_P(VertexAttributeTestES31, DrawArraysWithLargeStride)
2458 {
2459     GLint maxStride;
2460     glGetIntegerv(GL_MAX_VERTEX_ATTRIB_STRIDE, &maxStride);
2461     ASSERT_GL_NO_ERROR();
2462 
2463     GLint largeStride = std::min(maxStride, MAX_STRIDE_FOR_TEST);
2464     drawArraysWithStrideAndRelativeOffset(largeStride, 0);
2465 }
2466 
2467 // Verify using MAX_VERTEX_ATTRIB_RELATIVE_OFFSET as relativeOffset doesn't mess up the draw.
2468 // Use default value if the value of MAX_VERTEX_ATTRIB_RELATIVE_OFFSSET is too large for this test.
TEST_P(VertexAttributeTestES31,DrawArraysWithLargeRelativeOffset)2469 TEST_P(VertexAttributeTestES31, DrawArraysWithLargeRelativeOffset)
2470 {
2471     GLint maxRelativeOffset;
2472     glGetIntegerv(GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET, &maxRelativeOffset);
2473     ASSERT_GL_NO_ERROR();
2474 
2475     GLint largeRelativeOffset = std::min(maxRelativeOffset, MAX_RELATIVE_OFFSET_FOR_TEST);
2476     drawArraysWithStrideAndRelativeOffset(0, largeRelativeOffset);
2477 }
2478 
2479 // Test that vertex array object works correctly when render pipeline and compute pipeline are
2480 // crossly executed.
TEST_P(VertexAttributeTestES31,MixedComputeAndRenderPipelines)2481 TEST_P(VertexAttributeTestES31, MixedComputeAndRenderPipelines)
2482 {
2483     constexpr char kComputeShader[] =
2484         R"(#version 310 es
2485 layout(local_size_x=1) in;
2486 void main()
2487 {
2488 })";
2489     ANGLE_GL_COMPUTE_PROGRAM(computeProgram, kComputeShader);
2490 
2491     glViewport(0, 0, getWindowWidth(), getWindowHeight());
2492     glClearColor(0, 0, 0, 0);
2493 
2494     constexpr char kVertexShader[] =
2495         R"(#version 310 es
2496 precision mediump float;
2497 layout(location = 0) in vec4 position;
2498 layout(location = 2) in vec2 aOffset;
2499 layout(location = 3) in vec4 aColor;
2500 out vec4 vColor;
2501 void main() {
2502     vColor = aColor;
2503     gl_Position = position + vec4(aOffset, 0.0, 0.0);
2504 })";
2505 
2506     constexpr char kFragmentShader[] =
2507         R"(#version 310 es
2508 precision mediump float;
2509 in vec4 vColor;
2510 out vec4  color;
2511 void main() {
2512     color = vColor;
2513 })";
2514 
2515     ANGLE_GL_PROGRAM(renderProgram, kVertexShader, kFragmentShader);
2516 
2517     constexpr char kVertexShader1[] =
2518         R"(#version 310 es
2519 precision mediump float;
2520 layout(location = 1) in vec4 position;
2521 layout(location = 2) in vec2 aOffset;
2522 layout(location = 3) in vec4 aColor;
2523 out vec4 vColor;
2524 void main() {
2525     vColor = aColor;
2526     gl_Position = position + vec4(aOffset, 0.0, 0.0);
2527 })";
2528 
2529     ANGLE_GL_PROGRAM(renderProgram1, kVertexShader1, kFragmentShader);
2530 
2531     std::array<GLfloat, 8> offsets = {
2532         -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0,
2533     };
2534     GLBuffer offsetBuffer;
2535     glBindBuffer(GL_ARRAY_BUFFER, offsetBuffer);
2536     glBufferData(GL_ARRAY_BUFFER, offsets.size() * sizeof(GLfloat), offsets.data(), GL_STATIC_DRAW);
2537 
2538     std::array<GLfloat, 16> colors0 = {
2539         1.0, 0.0, 0.0, 1.0,  // Red
2540         0.0, 1.0, 0.0, 1.0,  // Green
2541         0.0, 0.0, 1.0, 1.0,  // Blue
2542         1.0, 1.0, 0.0, 1.0,  // Yellow
2543     };
2544     std::array<GLfloat, 16> colors1 = {
2545         1.0, 1.0, 0.0, 1.0,  // Yellow
2546         0.0, 0.0, 1.0, 1.0,  // Blue
2547         0.0, 1.0, 0.0, 1.0,  // Green
2548         1.0, 0.0, 0.0, 1.0,  // Red
2549     };
2550     GLBuffer colorBuffers[2];
2551     glBindBuffer(GL_ARRAY_BUFFER, colorBuffers[0]);
2552     glBufferData(GL_ARRAY_BUFFER, colors0.size() * sizeof(GLfloat), colors0.data(), GL_STATIC_DRAW);
2553     glBindBuffer(GL_ARRAY_BUFFER, colorBuffers[1]);
2554     glBufferData(GL_ARRAY_BUFFER, colors1.size() * sizeof(GLfloat), colors1.data(), GL_STATIC_DRAW);
2555 
2556     std::array<GLfloat, 16> positions = {1.0, 1.0, -1.0, 1.0,  -1.0, -1.0,
2557                                          1.0, 1.0, -1.0, -1.0, 1.0,  -1.0};
2558     GLBuffer positionBuffer;
2559     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
2560     glBufferData(GL_ARRAY_BUFFER, positions.size() * sizeof(GLfloat), positions.data(),
2561                  GL_STATIC_DRAW);
2562 
2563     const int kInstanceCount = 4;
2564     GLVertexArray vao[2];
2565     for (size_t i = 0u; i < 2u; ++i)
2566     {
2567         glBindVertexArray(vao[i]);
2568 
2569         glBindBuffer(GL_ARRAY_BUFFER, offsetBuffer);
2570         glEnableVertexAttribArray(2);
2571         glVertexAttribPointer(2, 2, GL_FLOAT, false, 0, 0);
2572         glVertexAttribDivisor(2, 1);
2573 
2574         glBindBuffer(GL_ARRAY_BUFFER, colorBuffers[i]);
2575         glEnableVertexAttribArray(3);
2576         glVertexAttribPointer(3, 4, GL_FLOAT, false, 0, 0);
2577         glVertexAttribDivisor(3, 1);
2578 
2579         glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
2580         glEnableVertexAttribArray(i);
2581         glVertexAttribPointer(i, 2, GL_FLOAT, false, 0, 0);
2582     }
2583 
2584     glClear(GL_COLOR_BUFFER_BIT);
2585 
2586     for (int i = 0; i < 3; i++)
2587     {
2588         glUseProgram(renderProgram);
2589         glBindVertexArray(vao[0]);
2590         glDrawArraysInstanced(GL_TRIANGLES, 0, 6, kInstanceCount);
2591 
2592         EXPECT_GL_NO_ERROR();
2593         EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 2, GLColor::red) << i;
2594         EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::green) << i;
2595         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue) << i;
2596         EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::yellow) << i;
2597 
2598         glBindVertexArray(vao[1]);
2599         glUseProgram(computeProgram);
2600         glDispatchCompute(1, 1, 1);
2601 
2602         glUseProgram(renderProgram1);
2603         glBindVertexArray(vao[1]);
2604         glDrawArraysInstanced(GL_TRIANGLES, 0, 6, kInstanceCount);
2605 
2606         EXPECT_GL_NO_ERROR();
2607         EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 2, GLColor::yellow) << i;
2608         EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::blue) << i;
2609         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green) << i;
2610         EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::red) << i;
2611     }
2612     ASSERT_GL_NO_ERROR();
2613 }
2614 
TEST_P(VertexAttributeTestES31,UseComputeShaderToUpdateVertexBuffer)2615 TEST_P(VertexAttributeTestES31, UseComputeShaderToUpdateVertexBuffer)
2616 {
2617     initTest();
2618     constexpr char kComputeShader[] =
2619         R"(#version 310 es
2620 layout(local_size_x=24) in;
2621 layout(std430, binding = 0) buffer buf {
2622     uint outData[24];
2623 };
2624 void main()
2625 {
2626     outData[gl_LocalInvocationIndex] = gl_LocalInvocationIndex;
2627 })";
2628 
2629     ANGLE_GL_COMPUTE_PROGRAM(computeProgram, kComputeShader);
2630     glUseProgram(mProgram);
2631 
2632     GLuint mid                                 = std::numeric_limits<GLuint>::max() >> 1;
2633     GLuint hi                                  = std::numeric_limits<GLuint>::max();
2634     std::array<GLuint, kVertexCount> inputData = {
2635         {0, 1, 2, 3, 254, 255, 256, mid - 1, mid, mid + 1, hi - 2, hi - 1, hi}};
2636     std::array<GLfloat, kVertexCount> expectedData;
2637     for (size_t i = 0; i < kVertexCount; i++)
2638     {
2639         expectedData[i] = Normalize(inputData[i]);
2640     }
2641 
2642     // Normalized unsigned int attribute will be classified as translated static attribute.
2643     TestData data(GL_UNSIGNED_INT, GL_TRUE, Source::BUFFER, inputData.data(), expectedData.data());
2644     GLint typeSize   = 4;
2645     GLsizei dataSize = kVertexCount * TypeStride(data.type);
2646     GLBuffer testBuffer;
2647     glBindBuffer(GL_ARRAY_BUFFER, testBuffer);
2648     glBufferData(GL_ARRAY_BUFFER, dataSize, data.inputData, GL_STATIC_DRAW);
2649     glVertexAttribPointer(mTestAttrib, typeSize, data.type, data.normalized, 0,
2650                           reinterpret_cast<void *>(data.bufferOffset));
2651     glEnableVertexAttribArray(mTestAttrib);
2652 
2653     glBindBuffer(GL_ARRAY_BUFFER, mExpectedBuffer);
2654     glBufferData(GL_ARRAY_BUFFER, dataSize, data.expectedData, GL_STATIC_DRAW);
2655     glVertexAttribPointer(mExpectedAttrib, typeSize, GL_FLOAT, GL_FALSE, 0, nullptr);
2656 
2657     // Draw twice to make sure that all static attributes dirty bits are synced.
2658     glDrawArrays(GL_TRIANGLES, 0, 6);
2659     glDrawArrays(GL_TRIANGLES, 0, 6);
2660     checkPixels();
2661 
2662     // Modify the testBuffer using a raw buffer
2663     glUseProgram(computeProgram);
2664     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, testBuffer);
2665     glDispatchCompute(1, 1, 1);
2666     glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
2667 
2668     // Draw again to verify that testBuffer has been changed.
2669     glUseProgram(mProgram);
2670     glDrawArrays(GL_TRIANGLES, 0, 6);
2671     EXPECT_GL_NO_ERROR();
2672     checkPixelsUnEqual();
2673 }
2674 
TEST_P(VertexAttributeTestES31,UsePpoComputeShaderToUpdateVertexBuffer)2675 TEST_P(VertexAttributeTestES31, UsePpoComputeShaderToUpdateVertexBuffer)
2676 {
2677     // PPOs are only supported in the Vulkan backend
2678     ANGLE_SKIP_TEST_IF(!isVulkanRenderer());
2679 
2680     initTest();
2681     constexpr char kComputeShader[] =
2682         R"(#version 310 es
2683 layout(local_size_x=24) in;
2684 layout(std430, binding = 0) buffer buf {
2685     uint outData[24];
2686 };
2687 void main()
2688 {
2689     outData[gl_LocalInvocationIndex] = gl_LocalInvocationIndex;
2690 })";
2691 
2692     glUseProgram(mProgram);
2693 
2694     GLuint mid                                 = std::numeric_limits<GLuint>::max() >> 1;
2695     GLuint hi                                  = std::numeric_limits<GLuint>::max();
2696     std::array<GLuint, kVertexCount> inputData = {
2697         {0, 1, 2, 3, 254, 255, 256, mid - 1, mid, mid + 1, hi - 2, hi - 1, hi}};
2698     std::array<GLfloat, kVertexCount> expectedData;
2699     for (size_t i = 0; i < kVertexCount; i++)
2700     {
2701         expectedData[i] = Normalize(inputData[i]);
2702     }
2703 
2704     // Normalized unsigned int attribute will be classified as translated static attribute.
2705     TestData data(GL_UNSIGNED_INT, GL_TRUE, Source::BUFFER, inputData.data(), expectedData.data());
2706     GLint typeSize   = 4;
2707     GLsizei dataSize = kVertexCount * TypeStride(data.type);
2708     GLBuffer testBuffer;
2709     glBindBuffer(GL_ARRAY_BUFFER, testBuffer);
2710     glBufferData(GL_ARRAY_BUFFER, dataSize, data.inputData, GL_STATIC_DRAW);
2711     glVertexAttribPointer(mTestAttrib, typeSize, data.type, data.normalized, 0,
2712                           reinterpret_cast<void *>(data.bufferOffset));
2713     glEnableVertexAttribArray(mTestAttrib);
2714 
2715     glBindBuffer(GL_ARRAY_BUFFER, mExpectedBuffer);
2716     glBufferData(GL_ARRAY_BUFFER, dataSize, data.expectedData, GL_STATIC_DRAW);
2717     glVertexAttribPointer(mExpectedAttrib, typeSize, GL_FLOAT, GL_FALSE, 0, nullptr);
2718 
2719     // Draw twice to make sure that all static attributes dirty bits are synced.
2720     glDrawArrays(GL_TRIANGLES, 0, 6);
2721     glDrawArrays(GL_TRIANGLES, 0, 6);
2722     checkPixels();
2723 
2724     // Modify the testBuffer using a raw buffer
2725     GLProgramPipeline pipeline;
2726     ANGLE_GL_COMPUTE_PROGRAM(computeProgram, kComputeShader);
2727     glProgramParameteri(computeProgram, GL_PROGRAM_SEPARABLE, GL_TRUE);
2728     glUseProgramStages(pipeline, GL_COMPUTE_SHADER_BIT, computeProgram);
2729     EXPECT_GL_NO_ERROR();
2730     glBindProgramPipeline(pipeline);
2731     EXPECT_GL_NO_ERROR();
2732     glUseProgram(0);
2733 
2734     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, testBuffer);
2735     glDispatchCompute(1, 1, 1);
2736     glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
2737 
2738     // Draw again to verify that testBuffer has been changed.
2739     glUseProgram(mProgram);
2740     glDrawArrays(GL_TRIANGLES, 0, 6);
2741     EXPECT_GL_NO_ERROR();
2742     checkPixelsUnEqual();
2743 }
2744 
TEST_P(VertexAttributeTestES31,UseComputeShaderToUpdateVertexBufferSamePpo)2745 TEST_P(VertexAttributeTestES31, UseComputeShaderToUpdateVertexBufferSamePpo)
2746 {
2747     // PPOs are only supported in the Vulkan backend
2748     ANGLE_SKIP_TEST_IF(!isVulkanRenderer());
2749 
2750     initTest();
2751     constexpr char kComputeShader[] =
2752         R"(#version 310 es
2753 layout(local_size_x=24) in;
2754 layout(std430, binding = 0) buffer buf {
2755     uint outData[24];
2756 };
2757 void main()
2758 {
2759     outData[gl_LocalInvocationIndex] = gl_LocalInvocationIndex;
2760 })";
2761 
2762     // Mark the program separable and re-link it so it can be bound to the PPO.
2763     glProgramParameteri(mProgram, GL_PROGRAM_SEPARABLE, GL_TRUE);
2764     glLinkProgram(mProgram);
2765     mProgram = CheckLinkStatusAndReturnProgram(mProgram, true);
2766 
2767     GLProgramPipeline pipeline;
2768     EXPECT_GL_NO_ERROR();
2769     glBindProgramPipeline(pipeline);
2770     glUseProgramStages(pipeline, GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, mProgram);
2771     EXPECT_GL_NO_ERROR();
2772     glUseProgram(0);
2773 
2774     GLuint mid                                 = std::numeric_limits<GLuint>::max() >> 1;
2775     GLuint hi                                  = std::numeric_limits<GLuint>::max();
2776     std::array<GLuint, kVertexCount> inputData = {
2777         {0, 1, 2, 3, 254, 255, 256, mid - 1, mid, mid + 1, hi - 2, hi - 1, hi}};
2778     std::array<GLfloat, kVertexCount> expectedData;
2779     for (size_t i = 0; i < kVertexCount; i++)
2780     {
2781         expectedData[i] = Normalize(inputData[i]);
2782     }
2783 
2784     // Normalized unsigned int attribute will be classified as translated static attribute.
2785     TestData data(GL_UNSIGNED_INT, GL_TRUE, Source::BUFFER, inputData.data(), expectedData.data());
2786     GLint typeSize   = 4;
2787     GLsizei dataSize = kVertexCount * TypeStride(data.type);
2788     GLBuffer testBuffer;
2789     glBindBuffer(GL_ARRAY_BUFFER, testBuffer);
2790     glBufferData(GL_ARRAY_BUFFER, dataSize, data.inputData, GL_STATIC_DRAW);
2791     glVertexAttribPointer(mTestAttrib, typeSize, data.type, data.normalized, 0,
2792                           reinterpret_cast<void *>(data.bufferOffset));
2793     glEnableVertexAttribArray(mTestAttrib);
2794 
2795     glBindBuffer(GL_ARRAY_BUFFER, mExpectedBuffer);
2796     glBufferData(GL_ARRAY_BUFFER, dataSize, data.expectedData, GL_STATIC_DRAW);
2797     glVertexAttribPointer(mExpectedAttrib, typeSize, GL_FLOAT, GL_FALSE, 0, nullptr);
2798 
2799     // Draw twice to make sure that all static attributes dirty bits are synced.
2800     glDrawArrays(GL_TRIANGLES, 0, 6);
2801     glDrawArrays(GL_TRIANGLES, 0, 6);
2802     checkPixels();
2803 
2804     // Modify the testBuffer using a raw buffer
2805     ANGLE_GL_COMPUTE_PROGRAM(computeProgram, kComputeShader);
2806     glProgramParameteri(computeProgram, GL_PROGRAM_SEPARABLE, GL_TRUE);
2807     glUseProgramStages(pipeline, GL_COMPUTE_SHADER_BIT, computeProgram);
2808     EXPECT_GL_NO_ERROR();
2809 
2810     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, testBuffer);
2811     glDispatchCompute(1, 1, 1);
2812     glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
2813 
2814     // Draw again to verify that testBuffer has been changed.
2815     glUseProgram(mProgram);
2816     glDrawArrays(GL_TRIANGLES, 0, 6);
2817     EXPECT_GL_NO_ERROR();
2818     checkPixelsUnEqual();
2819 }
2820 
2821 // Verify that using VertexAttribBinding after VertexAttribPointer won't mess up the draw.
TEST_P(VertexAttributeTestES31,ChangeAttribBindingAfterVertexAttribPointer)2822 TEST_P(VertexAttributeTestES31, ChangeAttribBindingAfterVertexAttribPointer)
2823 {
2824     initTest();
2825 
2826     constexpr GLint kInputStride = 2;
2827     constexpr GLint kFloatOffset = 10;
2828     std::array<GLfloat, kVertexCount + kFloatOffset> inputData1;
2829     std::array<GLfloat, kVertexCount * kInputStride> inputData2;
2830     for (size_t count = 0; count < kVertexCount; ++count)
2831     {
2832         inputData1[kFloatOffset + count] = static_cast<GLfloat>(count);
2833         inputData2[count * kInputStride] = static_cast<GLfloat>(count);
2834     }
2835 
2836     GLBuffer mBuffer1;
2837     glBindBuffer(GL_ARRAY_BUFFER, mBuffer1);
2838     glBufferData(GL_ARRAY_BUFFER, inputData1.size() * kFloatStride, inputData1.data(),
2839                  GL_STATIC_DRAW);
2840     // Update the format indexed mTestAttrib and the binding indexed mTestAttrib by
2841     // VertexAttribPointer.
2842     const GLintptr kOffset = static_cast<GLintptr>(kFloatStride * kFloatOffset);
2843     glVertexAttribPointer(mTestAttrib, 1, GL_FLOAT, GL_FALSE, 0,
2844                           reinterpret_cast<const GLvoid *>(kOffset));
2845     glEnableVertexAttribArray(mTestAttrib);
2846 
2847     constexpr GLint kTestBinding = 10;
2848     ASSERT_NE(mTestAttrib, kTestBinding);
2849 
2850     GLBuffer mBuffer2;
2851     glBindBuffer(GL_ARRAY_BUFFER, mBuffer2);
2852     glBufferData(GL_ARRAY_BUFFER, inputData2.size() * kFloatStride, inputData2.data(),
2853                  GL_STATIC_DRAW);
2854     glBindVertexBuffer(kTestBinding, mBuffer2, 0, kFloatStride * kInputStride);
2855 
2856     // The attribute indexed mTestAttrib is using the binding indexed kTestBinding in the first
2857     // draw.
2858     glVertexAttribBinding(mTestAttrib, kTestBinding);
2859     glDrawArrays(GL_TRIANGLES, 0, 6);
2860     checkPixels();
2861     EXPECT_GL_NO_ERROR();
2862 
2863     // The attribute indexed mTestAttrib is using the binding indexed mTestAttrib which should be
2864     // set after the call VertexAttribPointer before the first draw.
2865     glVertexAttribBinding(mTestAttrib, mTestAttrib);
2866     glDrawArrays(GL_TRIANGLES, 0, 6);
2867     checkPixels();
2868     EXPECT_GL_NO_ERROR();
2869 }
2870 
2871 // Verify that using VertexAttribFormat after VertexAttribPointer won't mess up the draw.
TEST_P(VertexAttributeTestES31,ChangeAttribFormatAfterVertexAttribPointer)2872 TEST_P(VertexAttributeTestES31, ChangeAttribFormatAfterVertexAttribPointer)
2873 {
2874     initTest();
2875 
2876     constexpr GLuint kFloatOffset = 10;
2877     std::array<GLfloat, kVertexCount + kFloatOffset> inputData;
2878     for (size_t count = 0; count < kVertexCount; ++count)
2879     {
2880         inputData[kFloatOffset + count] = static_cast<GLfloat>(count);
2881     }
2882 
2883     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
2884     glBufferData(GL_ARRAY_BUFFER, inputData.size() * kFloatStride, inputData.data(),
2885                  GL_STATIC_DRAW);
2886 
2887     // Call VertexAttribPointer on mTestAttrib. Now the relativeOffset of mTestAttrib should be 0.
2888     const GLuint kOffset = static_cast<GLuint>(kFloatStride * kFloatOffset);
2889     glVertexAttribPointer(mTestAttrib, 1, GL_FLOAT, GL_FALSE, 0, 0);
2890     glEnableVertexAttribArray(mTestAttrib);
2891 
2892     // Call VertexAttribFormat on mTestAttrib to modify the relativeOffset to kOffset.
2893     glVertexAttribFormat(mTestAttrib, 1, GL_FLOAT, GL_FALSE, kOffset);
2894 
2895     glDrawArrays(GL_TRIANGLES, 0, 6);
2896     checkPixels();
2897     EXPECT_GL_NO_ERROR();
2898 }
2899 
2900 // Verify that only updating a binding without updating the bound format won't mess up this draw.
TEST_P(VertexAttributeTestES31,OnlyUpdateBindingByBindVertexBuffer)2901 TEST_P(VertexAttributeTestES31, OnlyUpdateBindingByBindVertexBuffer)
2902 {
2903     // Default binding index for test
2904     constexpr GLint kTestBinding = 10;
2905     initOnlyUpdateBindingTest(kTestBinding);
2906 
2907     constexpr GLuint kTestFloatOffset2                               = kVertexCount * 2;
2908     std::array<GLfloat, kVertexCount> expectedData2                  = {};
2909     std::array<GLfloat, kTestFloatOffset2 + kVertexCount> inputData2 = {};
2910     for (size_t count = 0; count < kVertexCount; ++count)
2911     {
2912         GLfloat value2                        = static_cast<GLfloat>(count) * 2;
2913         expectedData2[count]                  = value2;
2914         inputData2[count + kTestFloatOffset2] = value2;
2915     }
2916 
2917     // Set another set of data for mExpectedAttrib.
2918     GLBuffer expectedBuffer2;
2919     glBindBuffer(GL_ARRAY_BUFFER, expectedBuffer2);
2920     glBufferData(GL_ARRAY_BUFFER, expectedData2.size() * kFloatStride, expectedData2.data(),
2921                  GL_STATIC_DRAW);
2922     glVertexAttribPointer(mExpectedAttrib, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
2923 
2924     GLBuffer testBuffer2;
2925     glBindBuffer(GL_ARRAY_BUFFER, testBuffer2);
2926     glBufferData(GL_ARRAY_BUFFER, inputData2.size() * kFloatStride, inputData2.data(),
2927                  GL_STATIC_DRAW);
2928 
2929     // Only update the binding kTestBinding in the second draw by BindVertexBuffer.
2930     glBindVertexBuffer(kTestBinding, testBuffer2, kTestFloatOffset2 * kFloatStride, kFloatStride);
2931 
2932     glDrawArrays(GL_TRIANGLES, 0, 6);
2933     checkPixels();
2934     EXPECT_GL_NO_ERROR();
2935 }
2936 
2937 // Verify that only updating a binding without updating the bound format won't mess up this draw.
TEST_P(VertexAttributeTestES31,OnlyUpdateBindingByVertexAttribPointer)2938 TEST_P(VertexAttributeTestES31, OnlyUpdateBindingByVertexAttribPointer)
2939 {
2940     // Default binding index for test
2941     constexpr GLint kTestBinding = 10;
2942     initOnlyUpdateBindingTest(kTestBinding);
2943 
2944     constexpr GLuint kTestFloatOffset2                               = kVertexCount * 3;
2945     std::array<GLfloat, kVertexCount> expectedData2                  = {};
2946     std::array<GLfloat, kTestFloatOffset2 + kVertexCount> inputData2 = {};
2947     for (size_t count = 0; count < kVertexCount; ++count)
2948     {
2949         GLfloat value2                        = static_cast<GLfloat>(count) * 3;
2950         expectedData2[count]                  = value2;
2951         inputData2[count + kTestFloatOffset2] = value2;
2952     }
2953 
2954     // Set another set of data for mExpectedAttrib.
2955     GLBuffer expectedBuffer2;
2956     glBindBuffer(GL_ARRAY_BUFFER, expectedBuffer2);
2957     glBufferData(GL_ARRAY_BUFFER, expectedData2.size() * kFloatStride, expectedData2.data(),
2958                  GL_STATIC_DRAW);
2959     glVertexAttribPointer(mExpectedAttrib, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
2960 
2961     GLBuffer testBuffer2;
2962     glBindBuffer(GL_ARRAY_BUFFER, testBuffer2);
2963     glBufferData(GL_ARRAY_BUFFER, inputData2.size() * kFloatStride, inputData2.data(),
2964                  GL_STATIC_DRAW);
2965 
2966     // Only update the binding kTestBinding in the second draw by VertexAttribPointer.
2967     glVertexAttribPointer(
2968         kTestBinding, 1, GL_FLOAT, GL_FALSE, 0,
2969         reinterpret_cast<const void *>(static_cast<uintptr_t>(kTestFloatOffset2 * kFloatStride)));
2970 
2971     glDrawArrays(GL_TRIANGLES, 0, 6);
2972     checkPixels();
2973     EXPECT_GL_NO_ERROR();
2974 }
2975 
2976 class VertexAttributeCachingTest : public VertexAttributeTest
2977 {
2978   protected:
VertexAttributeCachingTest()2979     VertexAttributeCachingTest() {}
2980 
2981     void testSetUp() override;
2982 
2983     template <typename DestT>
2984     static std::vector<GLfloat> GetExpectedData(const std::vector<GLubyte> &srcData,
2985                                                 GLenum attribType,
2986                                                 GLboolean normalized);
2987 
initDoubleAttribProgram()2988     void initDoubleAttribProgram()
2989     {
2990         constexpr char kVS[] =
2991             "attribute mediump vec4 position;\n"
2992             "attribute mediump vec4 test;\n"
2993             "attribute mediump vec4 expected;\n"
2994             "attribute mediump vec4 test2;\n"
2995             "attribute mediump vec4 expected2;\n"
2996             "varying mediump vec4 color;\n"
2997             "void main(void)\n"
2998             "{\n"
2999             "    gl_Position = position;\n"
3000             "    vec4 threshold = max(abs(expected) * 0.01, 1.0 / 64.0);\n"
3001             "    color = vec4(lessThanEqual(abs(test - expected), threshold));\n"
3002             "    vec4 threshold2 = max(abs(expected2) * 0.01, 1.0 / 64.0);\n"
3003             "    color += vec4(lessThanEqual(abs(test2 - expected2), threshold2));\n"
3004             "}\n";
3005 
3006         constexpr char kFS[] =
3007             "varying mediump vec4 color;\n"
3008             "void main(void)\n"
3009             "{\n"
3010             "    gl_FragColor = color;\n"
3011             "}\n";
3012 
3013         mProgram = CompileProgram(kVS, kFS);
3014         ASSERT_NE(0u, mProgram);
3015 
3016         mTestAttrib = glGetAttribLocation(mProgram, "test");
3017         ASSERT_NE(-1, mTestAttrib);
3018         mExpectedAttrib = glGetAttribLocation(mProgram, "expected");
3019         ASSERT_NE(-1, mExpectedAttrib);
3020 
3021         glUseProgram(mProgram);
3022     }
3023 
3024     struct AttribData
3025     {
3026         AttribData(GLenum typeIn, GLint sizeIn, GLboolean normalizedIn, GLsizei strideIn);
3027 
3028         GLenum type;
3029         GLint size;
3030         GLboolean normalized;
3031         GLsizei stride;
3032     };
3033 
3034     std::vector<AttribData> mTestData;
3035     std::map<GLenum, std::vector<GLfloat>> mExpectedData;
3036     std::map<GLenum, std::vector<GLfloat>> mNormExpectedData;
3037 };
3038 
AttribData(GLenum typeIn,GLint sizeIn,GLboolean normalizedIn,GLsizei strideIn)3039 VertexAttributeCachingTest::AttribData::AttribData(GLenum typeIn,
3040                                                    GLint sizeIn,
3041                                                    GLboolean normalizedIn,
3042                                                    GLsizei strideIn)
3043     : type(typeIn), size(sizeIn), normalized(normalizedIn), stride(strideIn)
3044 {}
3045 
3046 // static
3047 template <typename DestT>
GetExpectedData(const std::vector<GLubyte> & srcData,GLenum attribType,GLboolean normalized)3048 std::vector<GLfloat> VertexAttributeCachingTest::GetExpectedData(
3049     const std::vector<GLubyte> &srcData,
3050     GLenum attribType,
3051     GLboolean normalized)
3052 {
3053     std::vector<GLfloat> expectedData;
3054 
3055     const DestT *typedSrcPtr = reinterpret_cast<const DestT *>(srcData.data());
3056     size_t iterations        = srcData.size() / TypeStride(attribType);
3057 
3058     if (normalized)
3059     {
3060         for (size_t index = 0; index < iterations; ++index)
3061         {
3062             expectedData.push_back(Normalize(typedSrcPtr[index]));
3063         }
3064     }
3065     else
3066     {
3067         for (size_t index = 0; index < iterations; ++index)
3068         {
3069             expectedData.push_back(static_cast<GLfloat>(typedSrcPtr[index]));
3070         }
3071     }
3072 
3073     return expectedData;
3074 }
3075 
testSetUp()3076 void VertexAttributeCachingTest::testSetUp()
3077 {
3078     VertexAttributeTest::testSetUp();
3079 
3080     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
3081 
3082     std::vector<GLubyte> srcData;
3083     for (size_t count = 0; count < 4; ++count)
3084     {
3085         for (GLubyte i = 0; i < std::numeric_limits<GLubyte>::max(); ++i)
3086         {
3087             srcData.push_back(i);
3088         }
3089     }
3090 
3091     glBufferData(GL_ARRAY_BUFFER, srcData.size(), srcData.data(), GL_STATIC_DRAW);
3092 
3093     GLint viewportSize[4];
3094     glGetIntegerv(GL_VIEWPORT, viewportSize);
3095 
3096     std::vector<GLenum> attribTypes;
3097     attribTypes.push_back(GL_BYTE);
3098     attribTypes.push_back(GL_UNSIGNED_BYTE);
3099     attribTypes.push_back(GL_SHORT);
3100     attribTypes.push_back(GL_UNSIGNED_SHORT);
3101 
3102     if (getClientMajorVersion() >= 3)
3103     {
3104         attribTypes.push_back(GL_INT);
3105         attribTypes.push_back(GL_UNSIGNED_INT);
3106     }
3107 
3108     constexpr GLint kMaxSize     = 4;
3109     constexpr GLsizei kMaxStride = 4;
3110 
3111     for (GLenum attribType : attribTypes)
3112     {
3113         for (GLint attribSize = 1; attribSize <= kMaxSize; ++attribSize)
3114         {
3115             for (GLsizei stride = 1; stride <= kMaxStride; ++stride)
3116             {
3117                 mTestData.push_back(AttribData(attribType, attribSize, GL_FALSE, stride));
3118                 if (attribType != GL_FLOAT)
3119                 {
3120                     mTestData.push_back(AttribData(attribType, attribSize, GL_TRUE, stride));
3121                 }
3122             }
3123         }
3124     }
3125 
3126     mExpectedData[GL_BYTE]          = GetExpectedData<GLbyte>(srcData, GL_BYTE, GL_FALSE);
3127     mExpectedData[GL_UNSIGNED_BYTE] = GetExpectedData<GLubyte>(srcData, GL_UNSIGNED_BYTE, GL_FALSE);
3128     mExpectedData[GL_SHORT]         = GetExpectedData<GLshort>(srcData, GL_SHORT, GL_FALSE);
3129     mExpectedData[GL_UNSIGNED_SHORT] =
3130         GetExpectedData<GLushort>(srcData, GL_UNSIGNED_SHORT, GL_FALSE);
3131     mExpectedData[GL_INT]          = GetExpectedData<GLint>(srcData, GL_INT, GL_FALSE);
3132     mExpectedData[GL_UNSIGNED_INT] = GetExpectedData<GLuint>(srcData, GL_UNSIGNED_INT, GL_FALSE);
3133 
3134     mNormExpectedData[GL_BYTE] = GetExpectedData<GLbyte>(srcData, GL_BYTE, GL_TRUE);
3135     mNormExpectedData[GL_UNSIGNED_BYTE] =
3136         GetExpectedData<GLubyte>(srcData, GL_UNSIGNED_BYTE, GL_TRUE);
3137     mNormExpectedData[GL_SHORT] = GetExpectedData<GLshort>(srcData, GL_SHORT, GL_TRUE);
3138     mNormExpectedData[GL_UNSIGNED_SHORT] =
3139         GetExpectedData<GLushort>(srcData, GL_UNSIGNED_SHORT, GL_TRUE);
3140     mNormExpectedData[GL_INT]          = GetExpectedData<GLint>(srcData, GL_INT, GL_TRUE);
3141     mNormExpectedData[GL_UNSIGNED_INT] = GetExpectedData<GLuint>(srcData, GL_UNSIGNED_INT, GL_TRUE);
3142 }
3143 
3144 // In D3D11, we must sometimes translate buffer data into static attribute caches. We also use a
3145 // cache management scheme which garbage collects old attributes after we start using too much
3146 // cache data. This test tries to make as many attribute caches from a single buffer as possible
3147 // to stress-test the caching code.
TEST_P(VertexAttributeCachingTest,BufferMulticaching)3148 TEST_P(VertexAttributeCachingTest, BufferMulticaching)
3149 {
3150     ANGLE_SKIP_TEST_IF(IsAMD() && IsDesktopOpenGL());
3151 
3152     initBasicProgram();
3153 
3154     glEnableVertexAttribArray(mTestAttrib);
3155     glEnableVertexAttribArray(mExpectedAttrib);
3156 
3157     ASSERT_GL_NO_ERROR();
3158 
3159     for (const AttribData &data : mTestData)
3160     {
3161         const auto &expected =
3162             (data.normalized) ? mNormExpectedData[data.type] : mExpectedData[data.type];
3163 
3164         GLsizei baseStride = static_cast<GLsizei>(data.size) * data.stride;
3165         GLsizei stride     = TypeStride(data.type) * baseStride;
3166 
3167         glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
3168         glVertexAttribPointer(mTestAttrib, data.size, data.type, data.normalized, stride, nullptr);
3169         glBindBuffer(GL_ARRAY_BUFFER, 0);
3170         glVertexAttribPointer(mExpectedAttrib, data.size, GL_FLOAT, GL_FALSE,
3171                               sizeof(GLfloat) * baseStride, expected.data());
3172         drawQuad(mProgram, "position", 0.5f);
3173         ASSERT_GL_NO_ERROR();
3174         EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::white);
3175     }
3176 }
3177 
3178 // With D3D11 dirty bits for VertxArray11, we can leave vertex state unchanged if there aren't any
3179 // GL calls that affect it. This test targets leaving one vertex attribute unchanged between draw
3180 // calls while changing another vertex attribute enough that it clears the static buffer cache
3181 // after enough iterations. It validates the unchanged attributes don't get deleted incidentally.
TEST_P(VertexAttributeCachingTest,BufferMulticachingWithOneUnchangedAttrib)3182 TEST_P(VertexAttributeCachingTest, BufferMulticachingWithOneUnchangedAttrib)
3183 {
3184     ANGLE_SKIP_TEST_IF(IsAMD() && IsDesktopOpenGL());
3185 
3186     initDoubleAttribProgram();
3187 
3188     GLint testAttrib2Location = glGetAttribLocation(mProgram, "test2");
3189     ASSERT_NE(-1, testAttrib2Location);
3190     GLint expectedAttrib2Location = glGetAttribLocation(mProgram, "expected2");
3191     ASSERT_NE(-1, expectedAttrib2Location);
3192 
3193     glEnableVertexAttribArray(mTestAttrib);
3194     glEnableVertexAttribArray(mExpectedAttrib);
3195     glEnableVertexAttribArray(testAttrib2Location);
3196     glEnableVertexAttribArray(expectedAttrib2Location);
3197 
3198     ASSERT_GL_NO_ERROR();
3199 
3200     // Use an attribute that we know must be converted. This is a bit sensitive.
3201     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
3202     glVertexAttribPointer(testAttrib2Location, 3, GL_UNSIGNED_SHORT, GL_FALSE, 6, nullptr);
3203     glBindBuffer(GL_ARRAY_BUFFER, 0);
3204     glVertexAttribPointer(expectedAttrib2Location, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3,
3205                           mExpectedData[GL_UNSIGNED_SHORT].data());
3206 
3207     for (const auto &data : mTestData)
3208     {
3209         const auto &expected =
3210             (data.normalized) ? mNormExpectedData[data.type] : mExpectedData[data.type];
3211 
3212         GLsizei baseStride = static_cast<GLsizei>(data.size) * data.stride;
3213         GLsizei stride     = TypeStride(data.type) * baseStride;
3214 
3215         glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
3216         glVertexAttribPointer(mTestAttrib, data.size, data.type, data.normalized, stride, nullptr);
3217         glBindBuffer(GL_ARRAY_BUFFER, 0);
3218         glVertexAttribPointer(mExpectedAttrib, data.size, GL_FLOAT, GL_FALSE,
3219                               sizeof(GLfloat) * baseStride, expected.data());
3220         drawQuad(mProgram, "position", 0.5f);
3221 
3222         ASSERT_GL_NO_ERROR();
3223         EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 255, 255, 255);
3224     }
3225 }
3226 
3227 // Test that if there are gaps in the attribute indices, the attributes have their correct values.
TEST_P(VertexAttributeTest,UnusedVertexAttribWorks)3228 TEST_P(VertexAttributeTest, UnusedVertexAttribWorks)
3229 {
3230     constexpr char kVertexShader[] = R"(attribute vec2 position;
3231 attribute float actualValue;
3232 uniform float expectedValue;
3233 varying float result;
3234 void main()
3235 {
3236     result = (actualValue == expectedValue) ? 1.0 : 0.0;
3237     gl_Position = vec4(position, 0, 1);
3238 })";
3239 
3240     constexpr char kFragmentShader[] = R"(varying mediump float result;
3241 void main()
3242 {
3243     gl_FragColor = result > 0.0 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
3244 })";
3245 
3246     ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
3247 
3248     // Force a gap in attributes by using location 0 and 3
3249     GLint positionLocation = 0;
3250     glBindAttribLocation(program, positionLocation, "position");
3251 
3252     GLint attribLoc = 3;
3253     glBindAttribLocation(program, attribLoc, "actualValue");
3254 
3255     // Re-link the program to update the attribute locations
3256     glLinkProgram(program);
3257     ASSERT_TRUE(CheckLinkStatusAndReturnProgram(program, true));
3258 
3259     glUseProgram(program);
3260 
3261     GLint uniLoc = glGetUniformLocation(program, "expectedValue");
3262     ASSERT_NE(-1, uniLoc);
3263 
3264     glVertexAttribPointer(attribLoc, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
3265 
3266     ASSERT_NE(-1, positionLocation);
3267     setupQuadVertexBuffer(0.5f, 1.0f);
3268     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
3269     glEnableVertexAttribArray(positionLocation);
3270 
3271     std::array<GLfloat, 4> testValues = {{1, 2, 3, 4}};
3272     for (GLfloat testValue : testValues)
3273     {
3274         glUniform1f(uniLoc, testValue);
3275         glVertexAttrib1f(attribLoc, testValue);
3276         glDrawArrays(GL_TRIANGLES, 0, 6);
3277         ASSERT_GL_NO_ERROR();
3278         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3279     }
3280 }
3281 
3282 // Tests that repeatedly updating a disabled vertex attribute works as expected.
3283 // This covers an ANGLE bug where dirty bits for current values were ignoring repeated updates.
TEST_P(VertexAttributeTest,DisabledAttribUpdates)3284 TEST_P(VertexAttributeTest, DisabledAttribUpdates)
3285 {
3286     constexpr char kVertexShader[] = R"(attribute vec2 position;
3287 attribute float actualValue;
3288 uniform float expectedValue;
3289 varying float result;
3290 void main()
3291 {
3292     result = (actualValue == expectedValue) ? 1.0 : 0.0;
3293     gl_Position = vec4(position, 0, 1);
3294 })";
3295 
3296     constexpr char kFragmentShader[] = R"(varying mediump float result;
3297 void main()
3298 {
3299     gl_FragColor = result > 0.0 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
3300 })";
3301 
3302     ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
3303 
3304     glUseProgram(program);
3305     GLint attribLoc = glGetAttribLocation(program, "actualValue");
3306     ASSERT_NE(-1, attribLoc);
3307 
3308     GLint uniLoc = glGetUniformLocation(program, "expectedValue");
3309     ASSERT_NE(-1, uniLoc);
3310 
3311     glVertexAttribPointer(attribLoc, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
3312 
3313     GLint positionLocation = glGetAttribLocation(program, "position");
3314     ASSERT_NE(-1, positionLocation);
3315     setupQuadVertexBuffer(0.5f, 1.0f);
3316     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
3317     glEnableVertexAttribArray(positionLocation);
3318 
3319     std::array<GLfloat, 4> testValues = {{1, 2, 3, 4}};
3320     for (GLfloat testValue : testValues)
3321     {
3322         glUniform1f(uniLoc, testValue);
3323         glVertexAttrib1f(attribLoc, testValue);
3324         glDrawArrays(GL_TRIANGLES, 0, 6);
3325         ASSERT_GL_NO_ERROR();
3326         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3327     }
3328 }
3329 
3330 // Test that even inactive attributes are taken into account when checking for aliasing in case the
3331 // shader version is >= 3.00. GLSL ES 3.00.6 section 12.46.
TEST_P(VertexAttributeTestES3,InactiveAttributeAliasing)3332 TEST_P(VertexAttributeTestES3, InactiveAttributeAliasing)
3333 {
3334     constexpr char vertexShader[] =
3335         R"(#version 300 es
3336         precision mediump float;
3337         in vec4 input_active;
3338         in vec4 input_unused;
3339         void main()
3340         {
3341             gl_Position = input_active;
3342         })";
3343 
3344     constexpr char fragmentShader[] =
3345         R"(#version 300 es
3346         precision mediump float;
3347         out vec4 color;
3348         void main()
3349         {
3350             color = vec4(0.0);
3351         })";
3352 
3353     ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3354     glBindAttribLocation(program, 0, "input_active");
3355     glBindAttribLocation(program, 0, "input_unused");
3356     glLinkProgram(program);
3357     EXPECT_GL_NO_ERROR();
3358     GLint linkStatus = 0;
3359     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
3360     EXPECT_GL_FALSE(linkStatus);
3361 }
3362 
3363 // Test that enabling inactive attributes doesn't cause a crash
3364 // shader version is >= 3.00
TEST_P(VertexAttributeTestES3,EnabledButInactiveAttributes)3365 TEST_P(VertexAttributeTestES3, EnabledButInactiveAttributes)
3366 {
3367     // This is similar to runtest(), and the test is disabled there
3368     ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
3369 
3370     constexpr char testVertexShaderSource[] =
3371         R"(#version 300 es
3372 precision mediump float;
3373 in vec4 position;
3374 layout(location = 1) in vec4 test;
3375 layout(location = 2) in vec4 unused1;
3376 layout(location = 3) in vec4 unused2;
3377 layout(location = 4) in vec4 unused3;
3378 layout(location = 5) in vec4 expected;
3379 out vec4 color;
3380 void main(void)
3381 {
3382     gl_Position = position;
3383     vec4 threshold = max(abs(expected) * 0.01, 1.0 / 64.0);
3384     color = vec4(lessThanEqual(abs(test - expected), threshold));
3385 })";
3386 
3387     // Same as previous one, except it uses unused1/2 instead of test/expected, leaving unused3
3388     // unused
3389     constexpr char testVertexShader2Source[] =
3390         R"(#version 300 es
3391 precision mediump float;
3392 in vec4 position;
3393 layout(location = 1) in vec4 test;
3394 layout(location = 2) in vec4 unused1;
3395 layout(location = 3) in vec4 unused2;
3396 layout(location = 4) in vec4 unused3;
3397 layout(location = 5) in vec4 expected;
3398 out vec4 color;
3399 void main(void)
3400 {
3401     gl_Position = position;
3402     vec4 threshold = max(abs(unused2) * 0.01, 1.0 / 64.0);
3403     color = vec4(lessThanEqual(abs(unused1 - unused2), threshold));
3404 })";
3405 
3406     constexpr char testFragmentShaderSource[] =
3407         R"(#version 300 es
3408 precision mediump float;
3409 in vec4 color;
3410 out vec4 out_color;
3411 void main()
3412 {
3413     out_color = color;
3414 })";
3415 
3416     std::array<GLubyte, kVertexCount> inputData = {
3417         {0, 1, 2, 3, 4, 5, 6, 7, 125, 126, 127, 128, 129, 250, 251, 252, 253, 254, 255}};
3418     std::array<GLubyte, kVertexCount> inputData2;
3419     std::array<GLfloat, kVertexCount> expectedData;
3420     std::array<GLfloat, kVertexCount> expectedData2;
3421     for (size_t i = 0; i < kVertexCount; i++)
3422     {
3423         expectedData[i]  = inputData[i];
3424         inputData2[i]    = inputData[i] > 128 ? inputData[i] - 1 : inputData[i] + 1;
3425         expectedData2[i] = inputData2[i];
3426     }
3427 
3428     // Setup the program
3429     mProgram = CompileProgram(testVertexShaderSource, testFragmentShaderSource);
3430     ASSERT_NE(0u, mProgram);
3431 
3432     mTestAttrib = glGetAttribLocation(mProgram, "test");
3433     ASSERT_EQ(1, mTestAttrib);
3434     mExpectedAttrib = glGetAttribLocation(mProgram, "expected");
3435     ASSERT_EQ(5, mExpectedAttrib);
3436 
3437     GLint unused1Attrib = 2;
3438     GLint unused2Attrib = 3;
3439     GLint unused3Attrib = 4;
3440 
3441     // Test enabling an unused attribute before glUseProgram
3442     glEnableVertexAttribArray(unused3Attrib);
3443 
3444     glUseProgram(mProgram);
3445 
3446     // Setup the test data
3447     TestData data(GL_UNSIGNED_BYTE, GL_FALSE, Source::IMMEDIATE, inputData.data(),
3448                   expectedData.data());
3449     setupTest(data, 1);
3450 
3451     // Test enabling an unused attribute after glUseProgram
3452     glVertexAttribPointer(unused1Attrib, 1, data.type, data.normalized, 0, inputData2.data());
3453     glEnableVertexAttribArray(unused1Attrib);
3454 
3455     glVertexAttribPointer(unused2Attrib, 1, GL_FLOAT, GL_FALSE, 0, expectedData2.data());
3456     glEnableVertexAttribArray(unused2Attrib);
3457 
3458     // Run the test.  This shouldn't use the unused attributes.  Note that one of them is nullptr
3459     // which can cause a crash on certain platform-driver combination.
3460     drawQuad(mProgram, "position", 0.5f);
3461     checkPixels();
3462 
3463     // Now test with the same attributes enabled, but with a program with different attributes
3464     // active
3465     mProgram = CompileProgram(testVertexShader2Source, testFragmentShaderSource);
3466     ASSERT_NE(0u, mProgram);
3467 
3468     // Make sure all the attributes are in the same location
3469     ASSERT_EQ(glGetAttribLocation(mProgram, "unused1"), unused1Attrib);
3470     ASSERT_EQ(glGetAttribLocation(mProgram, "unused2"), unused2Attrib);
3471 
3472     glUseProgram(mProgram);
3473 
3474     // Run the test again.  unused1/2 were disabled in the previous run (as they were inactive in
3475     // the shader), but should be re-enabled now.
3476     drawQuad(mProgram, "position", 0.5f);
3477     checkPixels();
3478 }
3479 
3480 // Test that default integer attribute works correctly even if there is a gap in
3481 // attribute locations.
TEST_P(VertexAttributeTestES3,DefaultIntAttribWithGap)3482 TEST_P(VertexAttributeTestES3, DefaultIntAttribWithGap)
3483 {
3484     constexpr char kVertexShader[] = R"(#version 300 es
3485 layout(location = 0) in vec2 position;
3486 layout(location = 3) in int actualValue;
3487 uniform int expectedValue;
3488 out float result;
3489 void main()
3490 {
3491     result = (actualValue == expectedValue) ? 1.0 : 0.0;
3492     gl_Position = vec4(position, 0, 1);
3493 })";
3494 
3495     constexpr char kFragmentShader[] = R"(#version 300 es
3496 in mediump float result;
3497 layout(location = 0) out lowp vec4 out_color;
3498 void main()
3499 {
3500     out_color = result > 0.0 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
3501 })";
3502 
3503     ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
3504 
3505     // Re-link the program to update the attribute locations
3506     glLinkProgram(program);
3507     ASSERT_TRUE(CheckLinkStatusAndReturnProgram(program, true));
3508 
3509     glUseProgram(program);
3510 
3511     GLint uniLoc = glGetUniformLocation(program, "expectedValue");
3512     ASSERT_NE(-1, uniLoc);
3513 
3514     glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
3515 
3516     setupQuadVertexBuffer(0.5f, 1.0f);
3517     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
3518     glEnableVertexAttribArray(0);
3519 
3520     std::array<GLint, 4> testValues = {{1, 2, 3, 4}};
3521     for (GLfloat testValue : testValues)
3522     {
3523         glUniform1i(uniLoc, testValue);
3524         glVertexAttribI4i(3, testValue, 0, 0, 0);
3525         glDrawArrays(GL_TRIANGLES, 0, 6);
3526         ASSERT_GL_NO_ERROR();
3527         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3528     }
3529 }
3530 
3531 // Test that default unsigned integer attribute works correctly even if there is a gap in
3532 // attribute locations.
TEST_P(VertexAttributeTestES3,DefaultUIntAttribWithGap)3533 TEST_P(VertexAttributeTestES3, DefaultUIntAttribWithGap)
3534 {
3535     constexpr char kVertexShader[] = R"(#version 300 es
3536 layout(location = 0) in vec2 position;
3537 layout(location = 3) in uint actualValue;
3538 uniform uint expectedValue;
3539 out float result;
3540 void main()
3541 {
3542     result = (actualValue == expectedValue) ? 1.0 : 0.0;
3543     gl_Position = vec4(position, 0, 1);
3544 })";
3545 
3546     constexpr char kFragmentShader[] = R"(#version 300 es
3547 in mediump float result;
3548 layout(location = 0) out lowp vec4 out_color;
3549 void main()
3550 {
3551     out_color = result > 0.0 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
3552 })";
3553 
3554     ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
3555 
3556     // Re-link the program to update the attribute locations
3557     glLinkProgram(program);
3558     ASSERT_TRUE(CheckLinkStatusAndReturnProgram(program, true));
3559 
3560     glUseProgram(program);
3561 
3562     GLint uniLoc = glGetUniformLocation(program, "expectedValue");
3563     ASSERT_NE(-1, uniLoc);
3564 
3565     glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
3566 
3567     setupQuadVertexBuffer(0.5f, 1.0f);
3568     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
3569     glEnableVertexAttribArray(0);
3570 
3571     std::array<GLuint, 4> testValues = {{1, 2, 3, 4}};
3572     for (GLfloat testValue : testValues)
3573     {
3574         glUniform1ui(uniLoc, testValue);
3575         glVertexAttribI4ui(3, testValue, 0, 0, 0);
3576         glDrawArrays(GL_TRIANGLES, 0, 6);
3577         ASSERT_GL_NO_ERROR();
3578         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3579     }
3580 }
3581 
3582 // Tests that large strides that read past the end of the buffer work correctly.
3583 // Requires ES 3.1 to query MAX_VERTEX_ATTRIB_STRIDE.
TEST_P(VertexAttributeTestES31,LargeStride)3584 TEST_P(VertexAttributeTestES31, LargeStride)
3585 {
3586     struct Vertex
3587     {
3588         Vector4 position;
3589         Vector2 color;
3590     };
3591 
3592     constexpr uint32_t kColorOffset = offsetof(Vertex, color);
3593 
3594     // Get MAX_VERTEX_ATTRIB_STRIDE.
3595     GLint maxStride;
3596     glGetIntegerv(GL_MAX_VERTEX_ATTRIB_STRIDE, &maxStride);
3597 
3598     uint32_t bufferSize  = static_cast<uint32_t>(maxStride);
3599     uint32_t stride      = sizeof(Vertex);
3600     uint32_t numVertices = bufferSize / stride;
3601 
3602     // The last vertex fits in the buffer size. The last vertex stride extends past it.
3603     ASSERT_LT(numVertices * stride, bufferSize);
3604     ASSERT_GT(numVertices * stride + kColorOffset, bufferSize);
3605 
3606     RNG rng(0);
3607 
3608     std::vector<Vertex> vertexData(bufferSize, {Vector4(), Vector2()});
3609     std::vector<GLColor> expectedColors;
3610     for (uint32_t vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex)
3611     {
3612         int x = vertexIndex % getWindowWidth();
3613         int y = vertexIndex / getWindowWidth();
3614 
3615         // Generate and clamp a 2 component vector.
3616         Vector4 randomVec4 = RandomVec4(rng.randomInt(), 0.0f, 1.0f);
3617         GLColor randomColor(randomVec4);
3618         randomColor[2]     = 0;
3619         randomColor[3]     = 255;
3620         Vector4 clampedVec = randomColor.toNormalizedVector();
3621 
3622         vertexData[vertexIndex] = {Vector4(x, y, 0.0f, 1.0f),
3623                                    Vector2(clampedVec[0], clampedVec[1])};
3624         expectedColors.push_back(randomColor);
3625     }
3626 
3627     GLBuffer buffer;
3628     glBindBuffer(GL_ARRAY_BUFFER, buffer);
3629     glBufferData(GL_ARRAY_BUFFER, bufferSize, vertexData.data(), GL_STATIC_DRAW);
3630 
3631     vertexData.resize(numVertices);
3632 
3633     constexpr char kVS[] = R"(#version 310 es
3634 in vec4 pos;
3635 in vec2 color;
3636 out vec2 vcolor;
3637 void main()
3638 {
3639     vcolor = color;
3640     gl_Position = vec4(((pos.x + 0.5) / 64.0) - 1.0, ((pos.y + 0.5) / 64.0) - 1.0, 0, 1);
3641     gl_PointSize = 1.0;
3642 })";
3643 
3644     constexpr char kFS[] = R"(#version 310 es
3645 precision mediump float;
3646 in vec2 vcolor;
3647 out vec4 fcolor;
3648 void main()
3649 {
3650     fcolor = vec4(vcolor, 0.0, 1.0);
3651 })";
3652 
3653     ANGLE_GL_PROGRAM(program, kVS, kFS);
3654     glUseProgram(program);
3655 
3656     GLint posLoc = glGetAttribLocation(program, "pos");
3657     ASSERT_NE(-1, posLoc);
3658     GLint colorLoc = glGetAttribLocation(program, "color");
3659     ASSERT_NE(-1, colorLoc);
3660 
3661     glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, stride, nullptr);
3662     glEnableVertexAttribArray(posLoc);
3663     glVertexAttribPointer(colorLoc, 2, GL_FLOAT, GL_FALSE, stride,
3664                           reinterpret_cast<GLvoid *>(static_cast<uintptr_t>(kColorOffset)));
3665     glEnableVertexAttribArray(colorLoc);
3666 
3667     glDrawArrays(GL_POINTS, 0, numVertices);
3668 
3669     // Validate pixels.
3670     std::vector<GLColor> actualColors(getWindowWidth() * getWindowHeight());
3671     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
3672                  actualColors.data());
3673 
3674     actualColors.resize(numVertices);
3675 
3676     ASSERT_GL_NO_ERROR();
3677     EXPECT_EQ(expectedColors, actualColors);
3678 }
3679 
makeMismatchingSignsTestVS(uint32_t attribCount,uint16_t signedMask)3680 std::string VertexAttributeTestES31::makeMismatchingSignsTestVS(uint32_t attribCount,
3681                                                                 uint16_t signedMask)
3682 {
3683     std::ostringstream shader;
3684 
3685     shader << R"(#version 310 es
3686 precision highp float;
3687 
3688 // The signedness is determined by |signedMask|.
3689 )";
3690 
3691     for (uint32_t i = 0; i < attribCount; ++i)
3692     {
3693         shader << "in highp " << ((signedMask >> i & 1) == 0 ? "u" : "i") << "vec4 attrib" << i
3694                << ";\n";
3695     }
3696 
3697     shader << "flat out highp uvec4 v[" << attribCount << "];\n";
3698 
3699     shader << R"(
3700 void main() {
3701 )";
3702 
3703     for (uint32_t i = 0; i < attribCount; ++i)
3704     {
3705         shader << "v[" << i << "] = uvec4(attrib" << i << ");\n";
3706     }
3707 
3708     shader << R"(
3709     // gl_VertexID    x    y
3710     //      0        -1   -1
3711     //      1         1   -1
3712     //      2        -1    1
3713     //      3         1    1
3714     int bit0 = gl_VertexID & 1;
3715     int bit1 = gl_VertexID >> 1;
3716     gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, gl_VertexID % 2 == 0 ? -1 : 1, 1);
3717 })";
3718 
3719     return shader.str();
3720 }
3721 
makeMismatchingSignsTestFS(uint32_t attribCount)3722 std::string VertexAttributeTestES31::makeMismatchingSignsTestFS(uint32_t attribCount)
3723 {
3724     std::ostringstream shader;
3725 
3726     shader << R"(#version 310 es
3727 precision highp float;
3728 )";
3729 
3730     shader << "flat in highp uvec4 v[" << attribCount << "];\n";
3731 
3732     shader << R"(out vec4 fragColor;
3733 uniform vec4 colorScale;
3734 
3735 bool isOk(uvec4 inputVarying, uint index)
3736 {
3737     return inputVarying.x == index &&
3738         inputVarying.y == index * 2u &&
3739         inputVarying.z == index + 1u &&
3740         inputVarying.w == index + 0x12345u;
3741 }
3742 
3743 void main()
3744 {
3745     bool result = true;
3746 )";
3747     shader << "    for (uint index = 0u; index < " << attribCount << "u; ++index)\n";
3748     shader << R"({
3749         result = result && isOk(v[index], index);
3750     }
3751 
3752     fragColor = vec4(result) * colorScale;
3753 })";
3754 
3755     return shader.str();
3756 }
3757 
setupVertexAttribPointersForMismatchSignsTest(uint16_t currentSignedMask,uint16_t toggleMask)3758 uint16_t VertexAttributeTestES31::setupVertexAttribPointersForMismatchSignsTest(
3759     uint16_t currentSignedMask,
3760     uint16_t toggleMask)
3761 {
3762     uint16_t newSignedMask = currentSignedMask ^ toggleMask;
3763 
3764     for (uint32_t i = 0; i < 16; ++i)
3765     {
3766         if ((toggleMask >> i & 1) == 0)
3767         {
3768             continue;
3769         }
3770 
3771         const GLenum type = (newSignedMask >> i & 1) == 0 ? GL_UNSIGNED_INT : GL_INT;
3772         glVertexAttribIPointer(i, 4, type, sizeof(GLuint[4]),
3773                                reinterpret_cast<const void *>(sizeof(GLuint[4][4]) * i));
3774     }
3775 
3776     return newSignedMask;
3777 }
3778 
3779 // Test changing between matching and mismatching signedness of vertex attributes, when the
3780 // attribute changes type.
TEST_P(VertexAttributeTestES31,MismatchingSignsChangingAttributeType)3781 TEST_P(VertexAttributeTestES31, MismatchingSignsChangingAttributeType)
3782 {
3783     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_relaxed_vertex_attribute_type"));
3784 
3785     // GL supports a minimum of 16 vertex attributes, and gl_VertexID is counted as one.
3786     // The signedness pattern used here is:
3787     //
3788     //   0                14
3789     //   iiui uuii iuui uui
3790     //
3791     // Which is chosen such that there's no clear repeating / mirror pattern.
3792     const std::string vs = makeMismatchingSignsTestVS(15, 0x49CB);
3793     const std::string fs = makeMismatchingSignsTestFS(15);
3794 
3795     ANGLE_GL_PROGRAM(program, vs.c_str(), fs.c_str());
3796     for (uint32_t i = 0; i < 15; ++i)
3797     {
3798         char attribName[20];
3799         snprintf(attribName, sizeof(attribName), "attrib%u\n", i);
3800         glBindAttribLocation(program, i, attribName);
3801     }
3802     glLinkProgram(program);
3803     glUseProgram(program);
3804     ASSERT_GL_NO_ERROR();
3805 
3806     GLint colorScaleLoc = glGetUniformLocation(program, "colorScale");
3807     ASSERT_NE(-1, colorScaleLoc);
3808 
3809     GLuint data[15][4][4];
3810     for (GLuint i = 0; i < 15; ++i)
3811     {
3812         for (GLuint j = 0; j < 4; ++j)
3813         {
3814             // Match the expectation in the shader
3815             data[i][j][0] = i;
3816             data[i][j][1] = i * 2;
3817             data[i][j][2] = i + 1;
3818             data[i][j][3] = i + 0x12345;
3819         }
3820     }
3821 
3822     GLBuffer buffer;
3823     glBindBuffer(GL_ARRAY_BUFFER, buffer);
3824     glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
3825 
3826     // Randomly match and mismatch the component type
3827     uint16_t signedMask = setupVertexAttribPointersForMismatchSignsTest(0x0FA5, 0x7FFF);
3828 
3829     for (uint32_t i = 0; i < 15; ++i)
3830     {
3831         glEnableVertexAttribArray(i);
3832     }
3833 
3834     glClearColor(0, 0, 0, 0);
3835     glClear(GL_COLOR_BUFFER_BIT);
3836 
3837     glEnable(GL_BLEND);
3838     glBlendFunc(GL_ONE, GL_ONE);
3839 
3840     glUniform4f(colorScaleLoc, 1, 0, 0, 0);
3841     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3842 
3843     // Modify the attributes randomly and make sure tests still pass
3844 
3845     signedMask = setupVertexAttribPointersForMismatchSignsTest(signedMask, 0x3572);
3846     glUniform4f(colorScaleLoc, 0, 1, 0, 0);
3847     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3848 
3849     signedMask = setupVertexAttribPointersForMismatchSignsTest(signedMask, 0x4B1C);
3850     glUniform4f(colorScaleLoc, 0, 0, 1, 0);
3851     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3852 
3853     signedMask = setupVertexAttribPointersForMismatchSignsTest(signedMask, 0x19D6);
3854     glUniform4f(colorScaleLoc, 0, 0, 0, 1);
3855     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3856 
3857     // All channels must be 1
3858     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::white);
3859     ASSERT_GL_NO_ERROR();
3860 }
3861 
3862 // Test changing between matching and mismatching signedness of vertex attributes, when the
3863 // program itself changes the type.
TEST_P(VertexAttributeTestES31,MismatchingSignsChangingProgramType)3864 TEST_P(VertexAttributeTestES31, MismatchingSignsChangingProgramType)
3865 {
3866     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_relaxed_vertex_attribute_type"));
3867 
3868     // GL supports a minimum of 16 vertex attributes, and gl_VertexID is counted as one.
3869     constexpr uint32_t kAttribCount[4]      = {12, 9, 15, 7};
3870     constexpr uint32_t kAttribSignedMask[4] = {0x94f, 0x6A, 0x765B, 0x29};
3871 
3872     GLProgram programs[4];
3873 
3874     for (uint32_t progIndex = 0; progIndex < 4; ++progIndex)
3875     {
3876         const std::string vs =
3877             makeMismatchingSignsTestVS(kAttribCount[progIndex], kAttribSignedMask[progIndex]);
3878         const std::string fs = makeMismatchingSignsTestFS(kAttribCount[progIndex]);
3879 
3880         programs[progIndex].makeRaster(vs.c_str(), fs.c_str());
3881         for (uint32_t i = 0; i < kAttribCount[progIndex]; ++i)
3882         {
3883             char attribName[20];
3884             snprintf(attribName, sizeof(attribName), "attrib%u\n", i);
3885             glBindAttribLocation(programs[progIndex], i, attribName);
3886         }
3887         glLinkProgram(programs[progIndex]);
3888         glUseProgram(programs[progIndex]);
3889         ASSERT_GL_NO_ERROR();
3890     }
3891 
3892     GLuint data[15][4][4];
3893     for (GLuint i = 0; i < 15; ++i)
3894     {
3895         for (GLuint j = 0; j < 4; ++j)
3896         {
3897             // Match the expectation in the shader
3898             data[i][j][0] = i;
3899             data[i][j][1] = i * 2;
3900             data[i][j][2] = i + 1;
3901             data[i][j][3] = i + 0x12345;
3902         }
3903     }
3904 
3905     GLBuffer buffer;
3906     glBindBuffer(GL_ARRAY_BUFFER, buffer);
3907     glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
3908 
3909     // Randomly match and mismatch the component type
3910     setupVertexAttribPointersForMismatchSignsTest(0x55F8, 0x7FFF);
3911 
3912     for (uint32_t i = 0; i < 15; ++i)
3913     {
3914         glEnableVertexAttribArray(i);
3915     }
3916 
3917     glClearColor(0, 0, 0, 0);
3918     glClear(GL_COLOR_BUFFER_BIT);
3919 
3920     glEnable(GL_BLEND);
3921     glBlendFunc(GL_ONE, GL_ONE);
3922 
3923     glUseProgram(programs[0]);
3924     GLint colorScaleLoc = glGetUniformLocation(programs[0], "colorScale");
3925     ASSERT_NE(-1, colorScaleLoc);
3926     glUniform4f(colorScaleLoc, 1, 0, 0, 0);
3927     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3928 
3929     // Change the program, which have randomly different attribute component types and make sure
3930     // tests still pass
3931 
3932     glUseProgram(programs[1]);
3933     colorScaleLoc = glGetUniformLocation(programs[1], "colorScale");
3934     ASSERT_NE(-1, colorScaleLoc);
3935     glUniform4f(colorScaleLoc, 0, 1, 0, 0);
3936     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3937 
3938     glUseProgram(programs[2]);
3939     colorScaleLoc = glGetUniformLocation(programs[2], "colorScale");
3940     ASSERT_NE(-1, colorScaleLoc);
3941     glUniform4f(colorScaleLoc, 0, 0, 1, 0);
3942     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3943 
3944     glUseProgram(programs[3]);
3945     colorScaleLoc = glGetUniformLocation(programs[3], "colorScale");
3946     ASSERT_NE(-1, colorScaleLoc);
3947     glUniform4f(colorScaleLoc, 0, 0, 0, 1);
3948     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3949 
3950     // All channels must be 1
3951     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::white);
3952     ASSERT_GL_NO_ERROR();
3953 }
3954 
3955 // Test that aliasing attribute locations work with es 100 shaders.  Note that es 300 and above
3956 // don't allow vertex attribute aliasing.  This test excludes matrix types.
TEST_P(VertexAttributeTest,AliasingVectorAttribLocations)3957 TEST_P(VertexAttributeTest, AliasingVectorAttribLocations)
3958 {
3959     // http://anglebug.com/5180
3960     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
3961 
3962     // http://anglebug.com/3466
3963     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
3964 
3965     // http://anglebug.com/3467
3966     ANGLE_SKIP_TEST_IF(IsD3D());
3967 
3968     // TODO(anglebug.com/5491): iOS GLSL compiler rejects attribute aliasing.
3969     ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
3970 
3971     // This test needs 10 total attributes. All backends support this except some old Android
3972     // devices.
3973     GLint maxVertexAttribs = 0;
3974     glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
3975     ANGLE_SKIP_TEST_IF(maxVertexAttribs < 10);
3976 
3977     constexpr char kVS[] = R"(attribute vec4 position;
3978 // 4 aliasing attributes
3979 attribute float attr0f;
3980 attribute vec2 attr0v2;
3981 attribute vec3 attr0v3;
3982 attribute vec4 attr0v4;
3983 const vec4 attr0Expected = vec4(0.1, 0.2, 0.3, 0.4);
3984 
3985 // 2 aliasing attributes
3986 attribute vec2 attr1v2;
3987 attribute vec3 attr1v3;
3988 const vec3 attr1Expected = vec3(0.5, 0.6, 0.7);
3989 
3990 // 2 aliasing attributes
3991 attribute vec4 attr2v4;
3992 attribute float attr2f;
3993 const vec4 attr2Expected = vec4(0.8, 0.85, 0.9, 0.95);
3994 
3995 // 2 aliasing attributes
3996 attribute float attr3f1;
3997 attribute float attr3f2;
3998 const float attr3Expected = 1.0;
3999 
4000 uniform float attr0Select;
4001 uniform float attr1Select;
4002 uniform float attr2Select;
4003 uniform float attr3Select;
4004 
4005 // Each channel controlled by success from each set of aliasing attributes.  If a channel is 0, the
4006 // attribute test has failed.  Otherwise it will be 0.25, 0.5, 0.75 or 1.0, depending on how many
4007 // channels there are in the compared attribute (except attr3).
4008 varying mediump vec4 color;
4009 void main()
4010 {
4011     gl_Position = position;
4012 
4013     vec4 result = vec4(0);
4014 
4015     if (attr0Select < 0.5)
4016         result.r = abs(attr0f - attr0Expected.x) < 0.01 ? 0.25 : 0.0;
4017     else if (attr0Select < 1.5)
4018         result.r = all(lessThan(abs(attr0v2 - attr0Expected.xy), vec2(0.01))) ? 0.5 : 0.0;
4019     else if (attr0Select < 2.5)
4020         result.r = all(lessThan(abs(attr0v3 - attr0Expected.xyz), vec3(0.01))) ? 0.75 : 0.0;
4021     else
4022         result.r = all(lessThan(abs(attr0v4 - attr0Expected), vec4(0.01 )))? 1.0 : 0.0;
4023 
4024     if (attr1Select < 0.5)
4025         result.g = all(lessThan(abs(attr1v2 - attr1Expected.xy), vec2(0.01 )))? 0.5 : 0.0;
4026     else
4027         result.g = all(lessThan(abs(attr1v3 - attr1Expected), vec3(0.01 )))? 0.75 : 0.0;
4028 
4029     if (attr2Select < 0.5)
4030         result.b = abs(attr2f - attr2Expected.x) < 0.01 ? 0.25 : 0.0;
4031     else
4032         result.b = all(lessThan(abs(attr2v4 - attr2Expected), vec4(0.01))) ? 1.0 : 0.0;
4033 
4034     if (attr3Select < 0.5)
4035         result.a = abs(attr3f1 - attr3Expected) < 0.01 ? 0.25 : 0.0;
4036     else
4037         result.a = abs(attr3f2 - attr3Expected) < 0.01 ? 0.5 : 0.0;
4038 
4039     color = result;
4040 })";
4041 
4042     constexpr char kFS[] = R"(varying mediump vec4 color;
4043     void main(void)
4044     {
4045         gl_FragColor = color;
4046     })";
4047 
4048     // Compile shaders.
4049     GLuint program = CompileProgram(kVS, kFS);
4050     ASSERT_NE(program, 0u);
4051 
4052     // Setup bindings.
4053     glBindAttribLocation(program, 0, "attr0f");
4054     glBindAttribLocation(program, 0, "attr0v2");
4055     glBindAttribLocation(program, 0, "attr0v3");
4056     glBindAttribLocation(program, 0, "attr0v4");
4057     glBindAttribLocation(program, 1, "attr1v2");
4058     glBindAttribLocation(program, 1, "attr1v3");
4059     glBindAttribLocation(program, 2, "attr2v4");
4060     glBindAttribLocation(program, 2, "attr2f");
4061     glBindAttribLocation(program, 3, "attr3f1");
4062     glBindAttribLocation(program, 3, "attr3f2");
4063     EXPECT_GL_NO_ERROR();
4064 
4065     // Link program and get uniform locations.
4066     glLinkProgram(program);
4067     glUseProgram(program);
4068     GLint attr0SelectLoc = glGetUniformLocation(program, "attr0Select");
4069     GLint attr1SelectLoc = glGetUniformLocation(program, "attr1Select");
4070     GLint attr2SelectLoc = glGetUniformLocation(program, "attr2Select");
4071     GLint attr3SelectLoc = glGetUniformLocation(program, "attr3Select");
4072     ASSERT_NE(-1, attr0SelectLoc);
4073     ASSERT_NE(-1, attr1SelectLoc);
4074     ASSERT_NE(-1, attr2SelectLoc);
4075     ASSERT_NE(-1, attr3SelectLoc);
4076     EXPECT_GL_NO_ERROR();
4077 
4078     // Set values for attributes.
4079     glVertexAttrib4f(0, 0.1f, 0.2f, 0.3f, 0.4f);
4080     glVertexAttrib3f(1, 0.5f, 0.6f, 0.7f);
4081     glVertexAttrib4f(2, 0.8f, 0.85f, 0.9f, 0.95f);
4082     glVertexAttrib1f(3, 1.0f);
4083     glDisableVertexAttribArray(0);
4084     glDisableVertexAttribArray(1);
4085     glDisableVertexAttribArray(2);
4086     glDisableVertexAttribArray(3);
4087     EXPECT_GL_NO_ERROR();
4088 
4089     // Go through different combination of attributes and make sure reading through every alias is
4090     // correctly handled.
4091     GLColor expected;
4092     for (uint32_t attr0Select = 0; attr0Select < 4; ++attr0Select)
4093     {
4094         glUniform1f(attr0SelectLoc, attr0Select);
4095         expected.R = attr0Select * 64 + 63;
4096 
4097         for (uint32_t attr1Select = 0; attr1Select < 2; ++attr1Select)
4098         {
4099             glUniform1f(attr1SelectLoc, attr1Select);
4100             expected.G = attr1Select * 64 + 127;
4101 
4102             for (uint32_t attr2Select = 0; attr2Select < 2; ++attr2Select)
4103             {
4104                 glUniform1f(attr2SelectLoc, attr2Select);
4105                 expected.B = attr2Select * 192 + 63;
4106 
4107                 for (uint32_t attr3Select = 0; attr3Select < 2; ++attr3Select)
4108                 {
4109                     glUniform1f(attr3SelectLoc, attr3Select);
4110                     expected.A = attr3Select * 64 + 63;
4111 
4112                     drawQuad(program, "position", 0.5f);
4113                     EXPECT_GL_NO_ERROR();
4114                     EXPECT_PIXEL_COLOR_NEAR(0, 0, expected, 1);
4115                 }
4116             }
4117         }
4118     }
4119 }
4120 
4121 // Test that aliasing attribute locations work with es 100 shaders.  Note that es 300 and above
4122 // don't allow vertex attribute aliasing.  This test includes matrix types.
TEST_P(VertexAttributeTest,AliasingMatrixAttribLocations)4123 TEST_P(VertexAttributeTest, AliasingMatrixAttribLocations)
4124 {
4125     // http://anglebug.com/5180
4126     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
4127 
4128     // http://anglebug.com/3466
4129     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
4130 
4131     // http://anglebug.com/3467
4132     ANGLE_SKIP_TEST_IF(IsD3D());
4133 
4134     // TODO(anglebug.com/5491): iOS GLSL compiler rejects attribute aliasing.
4135     ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
4136 
4137     // This test needs 16 total attributes. All backends support this except some old Android
4138     // devices.
4139     GLint maxVertexAttribs = 0;
4140     glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
4141     ANGLE_SKIP_TEST_IF(maxVertexAttribs < 16);
4142 
4143     constexpr char kVS[] = R"(attribute vec4 position;
4144 // attributes aliasing location 0 and above
4145 attribute float attr0f;
4146 attribute mat3 attr0m3;
4147 attribute mat2 attr0m2;
4148 
4149 // attributes aliasing location 1 and above
4150 attribute vec4 attr1v4;
4151 
4152 // attributes aliasing location 2 and above
4153 attribute mat4 attr2m4;
4154 
4155 // attributes aliasing location 3 and above
4156 attribute mat2 attr3m2;
4157 
4158 // attributes aliasing location 5 and above
4159 attribute vec2 attr5v2;
4160 
4161 // In summary (attr prefix shortened to a):
4162 //
4163 // location 0: a0f a0m3[0] a0m2[0]
4164 // location 1:     a0m3[1] a0m2[1] a1v4
4165 // location 2:     a0m3[2]              a2m4[0]
4166 // location 3:                          a2m4[1] a3m2[0]
4167 // location 4:                          a2m4[2] a3m2[1]
4168 // location 5:                          a2m4[3]         a5v2
4169 
4170 const vec3 loc0Expected = vec3(0.05, 0.1, 0.15);
4171 const vec4 loc1Expected = vec4(0.2, 0.25, 0.3, 0.35);
4172 const vec4 loc2Expected = vec4(0.4, 0.45, 0.5, 0.55);
4173 const vec4 loc3Expected = vec4(0.6, 0.65, 0.7, 0.75);
4174 const vec4 loc4Expected = vec4(0.8, 0.85, 0.9, 0.95);
4175 const vec4 loc5Expected = vec4(0.25, 0.5, 0.75, 1.0);
4176 
4177 uniform float loc0Select;
4178 uniform float loc1Select;
4179 uniform float loc2Select;
4180 uniform float loc3Select;
4181 uniform float loc4Select;
4182 uniform float loc5Select;
4183 
4184 // Each channel controlled by success from each set of aliasing locations.  Locations 2 and 3
4185 // contribute to B together, while locations 4 and 5 contribute to A together.  If a channel is 0,
4186 // the attribute test has failed.  Otherwise it will be 1/N, 2/N, ..., 1, depending on how many
4187 // possible values there are for the controlling uniforms.
4188 varying mediump vec4 color;
4189 void main()
4190 {
4191     gl_Position = position;
4192 
4193     vec4 result = vec4(0);
4194 
4195     if (loc0Select < 0.5)
4196         result.r = abs(attr0f - loc0Expected.x) < 0.01 ? 0.333333 : 0.0;
4197     else if (loc0Select < 1.5)
4198         result.r = all(lessThan(abs(attr0m2[0] - loc0Expected.xy), vec2(0.01))) ? 0.666667 : 0.0;
4199     else
4200         result.r = all(lessThan(abs(attr0m3[0] - loc0Expected), vec3(0.01))) ? 1.0 : 0.0;
4201 
4202     if (loc1Select < 0.5)
4203         result.g = all(lessThan(abs(attr0m3[1] - loc1Expected.xyz), vec3(0.01))) ? 0.333333 : 0.0;
4204     else if (loc1Select < 1.5)
4205         result.g = all(lessThan(abs(attr0m2[1] - loc1Expected.xy), vec2(0.01))) ? 0.666667 : 0.0;
4206     else
4207         result.g = all(lessThan(abs(attr1v4 - loc1Expected), vec4(0.01))) ? 1.0 : 0.0;
4208 
4209     bool loc2Ok = false;
4210     bool loc3Ok = false;
4211 
4212     if (loc2Select < 0.5)
4213         loc2Ok = all(lessThan(abs(attr0m3[2] - loc2Expected.xyz), vec3(0.01)));
4214     else
4215         loc2Ok = all(lessThan(abs(attr2m4[0] - loc2Expected), vec4(0.01)));
4216 
4217     if (loc3Select < 0.5)
4218         loc3Ok = all(lessThan(abs(attr2m4[1] - loc3Expected), vec4(0.01)));
4219     else
4220         loc3Ok = all(lessThan(abs(attr3m2[0] - loc3Expected.xy), vec2(0.01)));
4221 
4222     if (loc2Ok && loc3Ok)
4223     {
4224         if (loc2Select < 0.5)
4225             if (loc3Select < 0.5)
4226                 result.b = 0.25;
4227             else
4228                 result.b = 0.5;
4229         else
4230             if (loc3Select < 0.5)
4231                 result.b = 0.75;
4232             else
4233                 result.b = 1.0;
4234     }
4235 
4236     bool loc4Ok = false;
4237     bool loc5Ok = false;
4238 
4239     if (loc4Select < 0.5)
4240         loc4Ok = all(lessThan(abs(attr2m4[2] - loc4Expected), vec4(0.01)));
4241     else
4242         loc4Ok = all(lessThan(abs(attr3m2[1] - loc4Expected.xy), vec2(0.01)));
4243 
4244     if (loc5Select < 0.5)
4245         loc5Ok = all(lessThan(abs(attr2m4[3] - loc5Expected), vec4(0.01)));
4246     else
4247         loc5Ok = all(lessThan(abs(attr5v2 - loc5Expected.xy), vec2(0.01)));
4248 
4249     if (loc4Ok && loc5Ok)
4250     {
4251         if (loc4Select < 0.5)
4252             if (loc5Select < 0.5)
4253                 result.a = 0.25;
4254             else
4255                 result.a = 0.5;
4256         else
4257             if (loc5Select < 0.5)
4258                 result.a = 0.75;
4259             else
4260                 result.a = 1.0;
4261     }
4262 
4263     color = result;
4264 })";
4265 
4266     constexpr char kFS[] = R"(varying mediump vec4 color;
4267     void main(void)
4268     {
4269         gl_FragColor = color;
4270     })";
4271 
4272     // Compile shaders.
4273     GLuint program = CompileProgram(kVS, kFS);
4274     ASSERT_NE(program, 0u);
4275 
4276     // Setup bindings.
4277     glBindAttribLocation(program, 0, "attr0f");
4278     glBindAttribLocation(program, 0, "attr0m3");
4279     glBindAttribLocation(program, 0, "attr0m2");
4280     glBindAttribLocation(program, 1, "attr1v4");
4281     glBindAttribLocation(program, 2, "attr2m4");
4282     glBindAttribLocation(program, 3, "attr3m2");
4283     glBindAttribLocation(program, 5, "attr5v2");
4284     EXPECT_GL_NO_ERROR();
4285 
4286     // Link program and get uniform locations.
4287     glLinkProgram(program);
4288     glUseProgram(program);
4289     EXPECT_GL_NO_ERROR();
4290 
4291     GLint loc0SelectLoc = glGetUniformLocation(program, "loc0Select");
4292     GLint loc1SelectLoc = glGetUniformLocation(program, "loc1Select");
4293     GLint loc2SelectLoc = glGetUniformLocation(program, "loc2Select");
4294     GLint loc3SelectLoc = glGetUniformLocation(program, "loc3Select");
4295     GLint loc4SelectLoc = glGetUniformLocation(program, "loc4Select");
4296     GLint loc5SelectLoc = glGetUniformLocation(program, "loc5Select");
4297     ASSERT_NE(-1, loc0SelectLoc);
4298     ASSERT_NE(-1, loc1SelectLoc);
4299     ASSERT_NE(-1, loc2SelectLoc);
4300     ASSERT_NE(-1, loc3SelectLoc);
4301     ASSERT_NE(-1, loc4SelectLoc);
4302     ASSERT_NE(-1, loc5SelectLoc);
4303     EXPECT_GL_NO_ERROR();
4304 
4305     // Set values for attributes.
4306     glVertexAttrib3f(0, 0.05, 0.1, 0.15);
4307     glVertexAttrib4f(1, 0.2, 0.25, 0.3, 0.35);
4308     glVertexAttrib4f(2, 0.4, 0.45, 0.5, 0.55);
4309     glVertexAttrib4f(3, 0.6, 0.65, 0.7, 0.75);
4310     glVertexAttrib4f(4, 0.8, 0.85, 0.9, 0.95);
4311     glVertexAttrib4f(5, 0.25, 0.5, 0.75, 1.0);
4312     glDisableVertexAttribArray(0);
4313     glDisableVertexAttribArray(1);
4314     glDisableVertexAttribArray(2);
4315     glDisableVertexAttribArray(3);
4316     glDisableVertexAttribArray(4);
4317     glDisableVertexAttribArray(5);
4318     EXPECT_GL_NO_ERROR();
4319 
4320     // Go through different combination of attributes and make sure reading through every alias is
4321     // correctly handled.
4322     GLColor expected;
4323     for (uint32_t loc0Select = 0; loc0Select < 3; ++loc0Select)
4324     {
4325         glUniform1f(loc0SelectLoc, loc0Select);
4326         expected.R = loc0Select * 85 + 85;
4327 
4328         for (uint32_t loc1Select = 0; loc1Select < 3; ++loc1Select)
4329         {
4330             glUniform1f(loc1SelectLoc, loc1Select);
4331             expected.G = loc1Select * 85 + 85;
4332 
4333             for (uint32_t loc2Select = 0; loc2Select < 2; ++loc2Select)
4334             {
4335                 glUniform1f(loc2SelectLoc, loc2Select);
4336 
4337                 for (uint32_t loc3Select = 0; loc3Select < 2; ++loc3Select)
4338                 {
4339                     glUniform1f(loc3SelectLoc, loc3Select);
4340                     expected.B = (loc2Select << 1 | loc3Select) * 64 + 63;
4341 
4342                     for (uint32_t loc4Select = 0; loc4Select < 2; ++loc4Select)
4343                     {
4344                         glUniform1f(loc4SelectLoc, loc4Select);
4345 
4346                         for (uint32_t loc5Select = 0; loc5Select < 2; ++loc5Select)
4347                         {
4348                             glUniform1f(loc5SelectLoc, loc5Select);
4349                             expected.A = (loc4Select << 1 | loc5Select) * 64 + 63;
4350 
4351                             drawQuad(program, "position", 0.5f);
4352                             EXPECT_GL_NO_ERROR();
4353                             EXPECT_PIXEL_COLOR_NEAR(0, 0, expected, 1);
4354                         }
4355                     }
4356                 }
4357             }
4358         }
4359     }
4360 }
4361 
4362 // Test that aliasing attribute locations work with differing precisions.
TEST_P(VertexAttributeTest,AliasingVectorAttribLocationsDifferingPrecisions)4363 TEST_P(VertexAttributeTest, AliasingVectorAttribLocationsDifferingPrecisions)
4364 {
4365     // http://anglebug.com/5180
4366     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
4367 
4368     // http://anglebug.com/3466
4369     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
4370 
4371     // http://anglebug.com/3467
4372     ANGLE_SKIP_TEST_IF(IsD3D());
4373 
4374     // TODO(anglebug.com/5491): iOS GLSL compiler rejects attribute aliasing.
4375     ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
4376 
4377     constexpr char kVS[] = R"(attribute vec4 position;
4378 // aliasing attributes.
4379 attribute mediump vec2 attr0v2;
4380 attribute highp vec3 attr0v3;
4381 const vec3 attr0Expected = vec3(0.125, 0.25, 0.375);
4382 
4383 // aliasing attributes.
4384 attribute highp vec2 attr1v2;
4385 attribute mediump vec3 attr1v3;
4386 const vec3 attr1Expected = vec3(0.5, 0.625, 0.75);
4387 
4388 uniform float attr0Select;
4389 uniform float attr1Select;
4390 
4391 // Each channel controlled by success from each set of aliasing attributes (R and G used only).  If
4392 // a channel is 0, the attribute test has failed.  Otherwise it will be 0.5 or 1.0.
4393 varying mediump vec4 color;
4394 void main()
4395 {
4396     gl_Position = position;
4397 
4398     vec4 result = vec4(0, 0, 0, 1);
4399 
4400     if (attr0Select < 0.5)
4401         result.r = all(lessThan(abs(attr0v2 - attr0Expected.xy), vec2(0.01))) ? 0.5 : 0.0;
4402     else
4403         result.r = all(lessThan(abs(attr0v3 - attr0Expected), vec3(0.01))) ? 1.0 : 0.0;
4404 
4405     if (attr1Select < 0.5)
4406         result.g = all(lessThan(abs(attr1v2 - attr1Expected.xy), vec2(0.01))) ? 0.5 : 0.0;
4407     else
4408         result.g = all(lessThan(abs(attr1v3 - attr1Expected), vec3(0.01))) ? 1.0 : 0.0;
4409 
4410     color = result;
4411 })";
4412 
4413     constexpr char kFS[] = R"(varying mediump vec4 color;
4414     void main(void)
4415     {
4416         gl_FragColor = color;
4417     })";
4418 
4419     // Compile shaders.
4420     GLuint program = CompileProgram(kVS, kFS);
4421     ASSERT_NE(program, 0u);
4422 
4423     // Setup bindings.
4424     glBindAttribLocation(program, 0, "attr0v2");
4425     glBindAttribLocation(program, 0, "attr0v3");
4426     glBindAttribLocation(program, 1, "attr1v2");
4427     glBindAttribLocation(program, 1, "attr1v3");
4428     EXPECT_GL_NO_ERROR();
4429 
4430     // Link program and get uniform locations.
4431     glLinkProgram(program);
4432     glUseProgram(program);
4433     GLint attr0SelectLoc = glGetUniformLocation(program, "attr0Select");
4434     GLint attr1SelectLoc = glGetUniformLocation(program, "attr1Select");
4435     ASSERT_NE(-1, attr0SelectLoc);
4436     ASSERT_NE(-1, attr1SelectLoc);
4437     EXPECT_GL_NO_ERROR();
4438 
4439     // Set values for attributes.
4440     glVertexAttrib3f(0, 0.125f, 0.25f, 0.375f);
4441     glVertexAttrib3f(1, 0.5f, 0.625f, 0.75f);
4442     glDisableVertexAttribArray(0);
4443     glDisableVertexAttribArray(1);
4444     EXPECT_GL_NO_ERROR();
4445 
4446     // Go through different combination of attributes and make sure reading through every alias is
4447     // correctly handled.
4448     GLColor expected;
4449     expected.B = 0;
4450     expected.A = 255;
4451     for (uint32_t attr0Select = 0; attr0Select < 2; ++attr0Select)
4452     {
4453         glUniform1f(attr0SelectLoc, attr0Select);
4454         expected.R = attr0Select * 128 + 127;
4455 
4456         for (uint32_t attr1Select = 0; attr1Select < 2; ++attr1Select)
4457         {
4458             glUniform1f(attr1SelectLoc, attr1Select);
4459             expected.G = attr1Select * 128 + 127;
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 // Test that unsupported vertex format specified on non-existing attribute doesn't crash.
TEST_P(VertexAttributeTest,VertexFormatConversionOfNonExistingAttribute)4469 TEST_P(VertexAttributeTest, VertexFormatConversionOfNonExistingAttribute)
4470 {
4471     constexpr char kVS[] = R"(precision highp float;
4472 attribute vec3 attr1;
4473 void main(void) {
4474    gl_Position = vec4(attr1, 1.0);
4475 })";
4476 
4477     constexpr char kFS[] = R"(precision highp float;
4478 void main(void) {
4479    gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
4480 })";
4481 
4482     GLBuffer emptyBuffer;
4483     glBindBuffer(GL_ARRAY_BUFFER, emptyBuffer);
4484 
4485     ANGLE_GL_PROGRAM(program, kVS, kFS);
4486     glBindAttribLocation(program, 0, "attr1");
4487     glLinkProgram(program);
4488     ASSERT_TRUE(CheckLinkStatusAndReturnProgram(program, true));
4489     glUseProgram(program);
4490 
4491     // Use the RGB8 format for non-existing attribute 1.
4492     glEnableVertexAttribArray(1);
4493     glVertexAttribPointer(1, 3, GL_UNSIGNED_BYTE, false, 1, 0);
4494 
4495     glDrawArrays(GL_TRIANGLES, 0, 3);
4496     EXPECT_GL_NO_ERROR();
4497 }
4498 
4499 // Covers a bug with integer formats and an element size larger than the vertex stride.
TEST_P(VertexAttributeTestES3,StrideSmallerThanIntegerElementSize)4500 TEST_P(VertexAttributeTestES3, StrideSmallerThanIntegerElementSize)
4501 {
4502     constexpr char kVS[] = R"(#version 300 es
4503 in vec4 position;
4504 in ivec2 intAttrib;
4505 in vec2 floatAttrib;
4506 out vec4 colorVarying;
4507 void main()
4508 {
4509     gl_Position = position;
4510     if (vec2(intAttrib) == floatAttrib)
4511     {
4512         colorVarying = vec4(0, 1, 0, 1);
4513     }
4514     else
4515     {
4516         colorVarying = vec4(1, 0, 0, 1);
4517     }
4518 })";
4519 
4520     constexpr char kFS[] = R"(#version 300 es
4521 precision mediump float;
4522 in vec4 colorVarying;
4523 out vec4 fragColor;
4524 void main()
4525 {
4526     fragColor = colorVarying;
4527 })";
4528 
4529     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
4530     glUseProgram(testProgram);
4531 
4532     GLBuffer positionBuffer;
4533     {
4534         const std::array<Vector3, 6> &quadVerts = GetQuadVertices();
4535 
4536         glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
4537         glBufferData(GL_ARRAY_BUFFER, quadVerts.size() * sizeof(quadVerts[0]), quadVerts.data(),
4538                      GL_STATIC_DRAW);
4539 
4540         GLint posLoc = glGetAttribLocation(testProgram, "position");
4541         ASSERT_NE(posLoc, -1);
4542         glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4543         glEnableVertexAttribArray(posLoc);
4544     }
4545 
4546     GLBuffer intBuffer;
4547     {
4548         std::array<GLbyte, 12> intData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
4549 
4550         glBindBuffer(GL_ARRAY_BUFFER, intBuffer);
4551         glBufferData(GL_ARRAY_BUFFER, intData.size() * sizeof(intData[0]), intData.data(),
4552                      GL_STATIC_DRAW);
4553 
4554         GLint intLoc = glGetAttribLocation(testProgram, "intAttrib");
4555         ASSERT_NE(intLoc, -1);
4556         glVertexAttribIPointer(intLoc, 2, GL_BYTE, 1, nullptr);
4557         glEnableVertexAttribArray(intLoc);
4558     }
4559 
4560     GLBuffer floatBuffer;
4561     {
4562         std::array<GLfloat, 12> floatData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
4563 
4564         glBindBuffer(GL_ARRAY_BUFFER, floatBuffer);
4565         glBufferData(GL_ARRAY_BUFFER, floatData.size() * sizeof(floatData[0]), floatData.data(),
4566                      GL_STATIC_DRAW);
4567 
4568         GLint floatLoc = glGetAttribLocation(testProgram, "floatAttrib");
4569         ASSERT_NE(floatLoc, -1);
4570         glVertexAttribPointer(floatLoc, 2, GL_FLOAT, GL_FALSE, 4, nullptr);
4571         glEnableVertexAttribArray(floatLoc);
4572     }
4573 
4574     glDrawArrays(GL_TRIANGLES, 0, 6);
4575 
4576     ASSERT_GL_NO_ERROR();
4577 
4578     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::green);
4579 }
4580 
4581 // Test that pipeline is recreated properly when switching from ARRAY buffer to client buffer,
4582 // while removing client buffer. Bug observed in Dragonmania game.
TEST_P(VertexAttributeTestES31,ArrayToClientBufferStride)4583 TEST_P(VertexAttributeTestES31, ArrayToClientBufferStride)
4584 {
4585     constexpr char kVS[] = R"(#version 310 es
4586 precision highp float;
4587 in vec4 in_pos;
4588 in vec4 in_color;
4589 out vec4 color;
4590 void main(void) {
4591    gl_Position = in_pos;
4592    color = in_color;
4593 })";
4594 
4595     constexpr char kFS[] = R"(#version 310 es
4596 precision highp float;
4597 in vec4 color;
4598 out vec4 frag_color;
4599 void main(void) {
4600    frag_color = color;
4601 })";
4602     swapBuffers();
4603 
4604     ANGLE_GL_PROGRAM(program, kVS, kFS);
4605     glUseProgram(program);
4606     GLint posLoc   = glGetAttribLocation(program, "in_pos");
4607     GLint colorLoc = glGetAttribLocation(program, "in_color");
4608     ASSERT_NE(posLoc, -1);
4609     ASSERT_NE(colorLoc, -1);
4610 
4611     const std::array<Vector3, 6> &quadVerts = GetQuadVertices();
4612     // Data for packed attributes.
4613     std::array<float, ((3 + 4) * 6)> data;
4614 
4615     float kYellow[4] = {1.0f, 1.0f, 0.0f, 1.0f};
4616     float kGreen[4]  = {0.0f, 1.0f, 0.0f, 1.0f};
4617 
4618     for (int i = 0; i < 6; i++)
4619     {
4620         memcpy(&data[i * (3 + 4)], &quadVerts[i], sizeof(Vector3));
4621         memcpy(&data[i * (3 + 4) + 3], &kYellow, 4 * sizeof(float));
4622     }
4623 
4624     {
4625         GLBuffer buffer;
4626         glBindBuffer(GL_ARRAY_BUFFER, buffer);
4627         glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(data[0]), data.data(), GL_STATIC_DRAW);
4628 
4629         glEnableVertexAttribArray(posLoc);
4630         glEnableVertexAttribArray(colorLoc);
4631 
4632         glVertexAttribPointer(posLoc, 3, GL_FLOAT, false, 28, reinterpret_cast<void *>(0));
4633         glVertexAttribPointer(colorLoc, 4, GL_FLOAT, false, 28, reinterpret_cast<void *>(12));
4634 
4635         glDrawArrays(GL_TRIANGLES, 0, 6);
4636         EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::yellow);
4637         EXPECT_GL_NO_ERROR();
4638         // Unbind before destroy.
4639         glBindBuffer(GL_ARRAY_BUFFER, 0);
4640     }
4641 
4642     // Modify color to green.
4643     for (int i = 0; i < 6; i++)
4644     {
4645         memcpy(&data[i * (3 + 4) + 3], &kGreen, 4 * sizeof(float));
4646     }
4647 
4648     // Provide client pointer.
4649     glVertexAttribPointer(posLoc, 3, GL_FLOAT, false, 28, data.data());
4650     glVertexAttribPointer(colorLoc, 4, GL_FLOAT, false, 28, &data[3]);
4651 
4652     glDrawArrays(GL_TRIANGLES, 0, 6);
4653     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::green);
4654     EXPECT_GL_NO_ERROR();
4655 }
4656 
4657 // Create a vertex array with an empty array buffer and attribute offsets.
4658 // This succeded in the end2end and capture/replay tests, but resulted in a trace
4659 // producing a GL error when using MEC.
4660 // Validation complained about the following:
4661 // "Client data cannot be used with a non-default vertex array object."
4662 
4663 // To capture this test with MEC run:
4664 // mkdir src/tests/capture_replay_tests/empty_array_buffer_test
4665 // ANGLE_CAPTURE_ENABLED=1 ANGLE_CAPTURE_FRAME_START=2 \
4666 // ANGLE_CAPTURE_FRAME_END=2 ANGLE_CAPTURE_LABEL=empty_array_buffer_test \
4667 // ANGLE_CAPTURE_OUT_DIR=src/tests/capture_replay_tests/empty_array_buffer_test \
4668 // ./out/Debug/angle_end2end_tests \
4669 // --gtest_filter="VertexAttributeTestES3.EmptyArrayBuffer/ES3_Vulkan"
TEST_P(VertexAttributeTestES3,EmptyArrayBuffer)4670 TEST_P(VertexAttributeTestES3, EmptyArrayBuffer)
4671 {
4672     GLVertexArray vertexArray;
4673     glBindVertexArray(vertexArray);
4674 
4675     GLBuffer emptyArrayBuffer;
4676     glBindBuffer(GL_ARRAY_BUFFER, emptyArrayBuffer);
4677 
4678     glEnableVertexAttribArray(0);
4679     glEnableVertexAttribArray(1);
4680     glEnableVertexAttribArray(2);
4681     glVertexAttribPointer(0, 4, GL_UNSIGNED_BYTE, GL_TRUE, 20, reinterpret_cast<const void *>(16));
4682     glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 20, reinterpret_cast<const void *>(8));
4683     glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 20, nullptr);
4684     EXPECT_GL_NO_ERROR();
4685 
4686     glBindBuffer(GL_ARRAY_BUFFER, 0);
4687     glBindVertexArray(0);
4688 
4689     EXPECT_GL_NO_ERROR();
4690 
4691     // Swap a frame for MEC
4692     swapBuffers();
4693 }
4694 
4695 // Set an attrib pointer and delete it's buffer after usage, while keeping the vertex array.
4696 // This will cause MEC to capture an invalid attribute pointer and also trigger
4697 // "Client data cannot be used with a non-default vertex array object."
TEST_P(VertexAttributeTestES3,InvalidAttribPointer)4698 TEST_P(VertexAttributeTestES3, InvalidAttribPointer)
4699 {
4700     GLVertexArray vertexArray;
4701     glBindVertexArray(vertexArray);
4702 
4703     std::array<GLbyte, 12> vertexData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
4704 
4705     {
4706         GLBuffer toBeDeletedArrayBuffer;
4707         glBindBuffer(GL_ARRAY_BUFFER, toBeDeletedArrayBuffer);
4708 
4709         glBufferData(GL_ARRAY_BUFFER, vertexData.size(), vertexData.data(), GL_DYNAMIC_DRAW);
4710 
4711         glEnableVertexAttribArray(0);
4712         glEnableVertexAttribArray(1);
4713 
4714         glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6, nullptr);
4715         glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6, reinterpret_cast<const void *>(6));
4716 
4717         glBindBuffer(GL_ARRAY_BUFFER, 0);
4718         glDisableVertexAttribArray(0);
4719         glDisableVertexAttribArray(1);
4720 
4721         EXPECT_GL_NO_ERROR();
4722     }
4723 
4724     // Set an attrib pointer that will be actually picked up by MEC, since the buffer will be kept.
4725     glEnableVertexAttribArray(0);
4726 
4727     GLBuffer arrayBuffer;
4728     glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
4729 
4730     glBufferData(GL_ARRAY_BUFFER, vertexData.size(), vertexData.data(), GL_DYNAMIC_DRAW);
4731 
4732     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3, reinterpret_cast<const void *>(3));
4733 
4734     EXPECT_GL_NO_ERROR();
4735 
4736     // Swap a frame for MEC
4737     swapBuffers();
4738 
4739     glBindBuffer(GL_ARRAY_BUFFER, 0);
4740     glEnableVertexAttribArray(0);
4741 }
4742 
4743 // Test maxinum attribs full of Client buffers and then switch to mixed.
TEST_P(VertexAttributeTestES3,fullClientBuffersSwitchToMixed)4744 TEST_P(VertexAttributeTestES3, fullClientBuffersSwitchToMixed)
4745 {
4746     GLint maxAttribs;
4747     glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttribs);
4748     ASSERT_GL_NO_ERROR();
4749 
4750     // Reserve one attrib for position
4751     GLint drawAttribs = maxAttribs - 1;
4752 
4753     GLuint program = compileMultiAttribProgram(drawAttribs);
4754     ASSERT_NE(0u, program);
4755 
4756     const std::array<Vector2, 4> kIndexedQuadVertices = {{
4757         Vector2(-1.0f, 1.0f),
4758         Vector2(-1.0f, -1.0f),
4759         Vector2(1.0f, -1.0f),
4760         Vector2(1.0f, 1.0f),
4761     }};
4762 
4763     GLsizei stride = (maxAttribs + 1) * sizeof(GLfloat);
4764 
4765     constexpr std::array<GLushort, 6> kIndexedQuadIndices = {{0, 1, 2, 0, 2, 3}};
4766     GLuint indexBuffer                                    = 0;
4767     glGenBuffers(1, &indexBuffer);
4768 
4769     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
4770     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndexedQuadIndices), kIndexedQuadIndices.data(),
4771                  GL_STATIC_DRAW);
4772 
4773     // Vertex drawAttribs color attributes plus position (x, y).
4774     GLint totalComponents = drawAttribs + 2;
4775     std::vector<GLfloat> vertexData(totalComponents * 4, 0.0f);
4776     for (GLint index = 0; index < 4; ++index)
4777     {
4778         vertexData[index * totalComponents + drawAttribs]     = kIndexedQuadVertices[index].x();
4779         vertexData[index * totalComponents + drawAttribs + 1] = kIndexedQuadVertices[index].y();
4780     }
4781 
4782     GLfloat attributeValue = 0.0f;
4783     GLfloat delta          = 1.0f / 256.0f;
4784     for (GLint attribIndex = 0; attribIndex < drawAttribs; ++attribIndex)
4785     {
4786         vertexData[attribIndex]                       = attributeValue;
4787         vertexData[attribIndex + totalComponents]     = attributeValue;
4788         vertexData[attribIndex + totalComponents * 2] = attributeValue;
4789         vertexData[attribIndex + totalComponents * 3] = attributeValue;
4790         attributeValue += delta;
4791     }
4792 
4793     glUseProgram(program);
4794     for (GLint attribIndex = 0; attribIndex < drawAttribs; ++attribIndex)
4795     {
4796         std::stringstream attribStream;
4797         attribStream << "a" << attribIndex;
4798         GLint location = glGetAttribLocation(program, attribStream.str().c_str());
4799         ASSERT_NE(-1, location);
4800         glVertexAttribPointer(location, 1, GL_FLOAT, GL_FALSE, stride,
4801                               vertexData.data() + attribIndex);
4802         glEnableVertexAttribArray(location);
4803     }
4804     GLint posLoc = glGetAttribLocation(program, "position");
4805     ASSERT_NE(-1, posLoc);
4806     glEnableVertexAttribArray(posLoc);
4807     glVertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, stride, vertexData.data() + drawAttribs);
4808     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
4809 
4810     // the result color should be (0 + 1 + 2 + ... + 14)/256 * 255;
4811     EXPECT_GL_NO_ERROR();
4812     EXPECT_PIXEL_NEAR(0, 0, 105, 0, 0, 255, 1);
4813 
4814     // disable a few attribute use default attribute color
4815     GLint l0  = glGetAttribLocation(program, "a0");
4816     GLint l5  = glGetAttribLocation(program, "a5");
4817     GLint l13 = glGetAttribLocation(program, "a13");
4818     glDisableVertexAttribArray(l0);
4819     glVertexAttrib1f(l0, 1.0f / 16.0f);
4820     glDisableVertexAttribArray(l5);
4821     glVertexAttrib1f(l5, 1.0f / 16.0f);
4822     glDisableVertexAttribArray(l13);
4823     glVertexAttrib1f(l13, 1.0f / 16.0f);
4824 
4825     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
4826 
4827     EXPECT_GL_NO_ERROR();
4828     EXPECT_PIXEL_NEAR(0, 0, 134, 0, 0, 255, 1);
4829 
4830     // disable all the client buffers.
4831     for (GLint attribIndex = 0; attribIndex < drawAttribs; ++attribIndex)
4832     {
4833         std::stringstream attribStream;
4834         attribStream << "a" << attribIndex;
4835         GLint location = glGetAttribLocation(program, attribStream.str().c_str());
4836         ASSERT_NE(-1, location);
4837         glDisableVertexAttribArray(location);
4838         glVertexAttrib1f(location, 1.0f / 16.0f);
4839     }
4840 
4841     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
4842 
4843     EXPECT_GL_NO_ERROR();
4844     EXPECT_PIXEL_NEAR(0, 0, 239, 0, 0, 255, 1);
4845 
4846     // enable all the client buffers.
4847     for (GLint attribIndex = 0; attribIndex < drawAttribs; ++attribIndex)
4848     {
4849         std::stringstream attribStream;
4850         attribStream << "a" << attribIndex;
4851         GLint location = glGetAttribLocation(program, attribStream.str().c_str());
4852         ASSERT_NE(-1, location);
4853         glVertexAttribPointer(location, 1, GL_FLOAT, GL_FALSE, stride,
4854                               vertexData.data() + attribIndex);
4855         glEnableVertexAttribArray(location);
4856     }
4857     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
4858     EXPECT_GL_NO_ERROR();
4859     EXPECT_PIXEL_NEAR(0, 0, 105, 0, 0, 255, 1);
4860 }
4861 
4862 // Test bind an empty buffer for vertex attribute does not crash
TEST_P(VertexAttributeTestES3,emptyBuffer)4863 TEST_P(VertexAttributeTestES3, emptyBuffer)
4864 {
4865     constexpr char vs2[] =
4866         R"(#version 300 es
4867             in uvec4 attr0;
4868             void main()
4869             {
4870                 gl_Position = vec4(attr0.x, 0.0, 0.0, 0.0);
4871             })";
4872     constexpr char fs[] =
4873         R"(#version 300 es
4874             precision highp float;
4875             out vec4 color;
4876             void main()
4877             {
4878                 color = vec4(1.0, 0.0, 0.0, 1.0);
4879             })";
4880     GLuint program2 = CompileProgram(vs2, fs);
4881     GLBuffer buf;
4882     glBindBuffer(GL_ARRAY_BUFFER, buf);
4883     glEnableVertexAttribArray(0);
4884     glVertexAttribIPointer(0, 4, GL_UNSIGNED_BYTE, 0, 0);
4885     glVertexAttribDivisor(0, 2);
4886     glUseProgram(program2);
4887     glDrawArrays(GL_POINTS, 0, 1);
4888 
4889     swapBuffers();
4890 }
4891 
4892 // This is a test for use with ANGLE's Capture/Replay.
4893 // It emulates a situation we see in some apps, where attribs are passed in but may not be used.
4894 // In particular, that test asks for all active attributes and iterates through each one. Before any
4895 // changes to FrameCapture, this will create calls that look up attributes that are considered
4896 // unused on some platforms, making the trace non-portable. Whether they are used depends on how
4897 // well the stack optimizes the shader pipeline. In this instance, we are just passing them across
4898 // the pipeline boundary where they are dead in the fragment shader, but other cases have included
4899 // attributes passed to empty functions, or some eliminated with math. The more optimizations
4900 // applied by the driver, the higher chance of getting an unused attribute.
TEST_P(VertexAttributeTestES3,UnusedAttribsMEC)4901 TEST_P(VertexAttributeTestES3, UnusedAttribsMEC)
4902 {
4903     constexpr char vertexShader[] =
4904         R"(#version 300 es
4905         precision mediump float;
4906         in vec4 position;
4907         in vec4 input_unused;
4908         out vec4 passthrough;
4909         void main()
4910         {
4911             passthrough = input_unused;
4912             gl_Position = position;
4913         })";
4914 
4915     constexpr char fragmentShader[] =
4916         R"(#version 300 es
4917         precision mediump float;
4918         in vec4 passthrough;
4919         out vec4 color;
4920         void main()
4921         {
4922             // ignore passthrough - this makes it unused with cross stage optimizations
4923             color = vec4(1.0);
4924         })";
4925 
4926     GLuint program = CompileProgram(vertexShader, fragmentShader);
4927     glUseProgram(program);
4928 
4929     // Set up vertex data
4930     GLBuffer positionBuffer;
4931     const std::array<Vector3, 6> &quadVerts = GetQuadVertices();
4932     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
4933     glBufferData(GL_ARRAY_BUFFER, quadVerts.size() * sizeof(quadVerts[0]), quadVerts.data(),
4934                  GL_STATIC_DRAW);
4935 
4936     // Loop through a sequence multiple times, so MEC can capture it.
4937     // Ask about vertex attribs and set them up, regardless of whether they are used.
4938     // This matches behavior seen in some apps.
4939     for (int i = 0; i < 10; i++)
4940     {
4941         // Look up the number of attribs
4942         GLint activeAttribCount = 0;
4943         glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &activeAttribCount);
4944 
4945         // Look up how big they might get
4946         GLint maxActiveAttribLength = 0;
4947         glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxActiveAttribLength);
4948 
4949         GLsizei attribLength  = 0;
4950         GLint attribSize      = 0;
4951         GLenum attribType     = 0;
4952         GLchar attribName[16] = {0};
4953         ASSERT(maxActiveAttribLength < 16);
4954 
4955         // Look up each attribute and set them up
4956         for (int j = 0; j < activeAttribCount; j++)
4957         {
4958             glGetActiveAttrib(program, j, maxActiveAttribLength, &attribLength, &attribSize,
4959                               &attribType, attribName);
4960             GLint posLoc = glGetAttribLocation(program, attribName);
4961             ASSERT_NE(posLoc, -1);
4962             glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, j, nullptr);
4963             glEnableVertexAttribArray(posLoc);
4964         }
4965 
4966         // Draw and swap on each loop to trigger MEC
4967         glDrawArrays(GL_TRIANGLES, 0, 6);
4968         EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::white);
4969         swapBuffers();
4970     }
4971 }
4972 
4973 // Test that a particular vertex attribute naming does not affect the functionality.
4974 // Tests the vertex attrib aliasing part. Note that aliasing works with es 100 shaders.
TEST_P(VertexAttributeTest,AliasingAttribNaming)4975 TEST_P(VertexAttributeTest, AliasingAttribNaming)
4976 {
4977     // http://anglebug.com/5180
4978     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
4979 
4980     // http://anglebug.com/3466
4981     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
4982 
4983     // http://anglebug.com/3467
4984     ANGLE_SKIP_TEST_IF(IsD3D());
4985 
4986     // TODO(anglebug.com/5491): iOS GLSL compiler rejects attribute aliasing.
4987     ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
4988 
4989     // This test needs 16 total attributes. All backends support this except some old Android
4990     // devices.
4991     GLint maxVertexAttribs = 0;
4992     glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
4993     ANGLE_SKIP_TEST_IF(maxVertexAttribs < 16);
4994 
4995     constexpr char kVS[] = R"(attribute vec4 position;
4996 // attributes aliasing location 0 and above
4997 attribute mat3 a;
4998 attribute mat2 a_;
4999 
5000 // attributes aliasing location 1 and above
5001 attribute vec4 a_1;
5002 
5003 // attributes aliasing location 2 and above
5004 attribute mat4 a_0;
5005 
5006 // In summary:
5007 //
5008 // location 0: a[0] a_[0]
5009 // location 1: a[1] a_[1] a_1
5010 // location 2: a[2]          a_0[0]
5011 // location 3:               a_0[1] (untested)
5012 // location 4:               a_0[2] (untested)
5013 // location 5:               a_0[3] (untested)
5014 
5015 const vec3 loc0Expected = vec3(0.05, 0.1, 0.15);
5016 const vec4 loc1Expected = vec4(0.2, 0.25, 0.3, 0.35);
5017 const vec4 loc2Expected = vec4(0.4, 0.45, 0.5, 0.55);
5018 
5019 uniform float loc0Select;
5020 uniform float loc1Select;
5021 uniform float loc2Select;
5022 
5023 // Each channel controlled by success from each set of aliasing locations.  If a channel is 0,
5024 // the attribute test has failed.  Otherwise it will be 1/N, 2/N, ..., 1, depending on how many
5025 // possible values there are for the controlling uniforms.
5026 varying mediump vec4 color;
5027 void main()
5028 {
5029     gl_Position = position;
5030 
5031     vec4 result = vec4(0);
5032 
5033     if (loc0Select < 0.5)
5034         result.r = all(lessThan(abs(a[0] - loc0Expected.xyz), vec3(0.01))) ? 0.5 : 0.0;
5035     else
5036         result.r = all(lessThan(abs(a_[0] - loc0Expected.xy), vec2(0.01))) ? 1.0 : 0.0;
5037 
5038     if (loc1Select < 0.5)
5039         result.g = all(lessThan(abs(a[1] - loc1Expected.xyz), vec3(0.01))) ? 0.333333 : 0.0;
5040     else if (loc1Select < 1.5)
5041         result.g = all(lessThan(abs(a_[1] - loc1Expected.xy), vec2(0.01))) ? 0.666667 : 0.0;
5042     else
5043         result.g = all(lessThan(abs(a_1 - loc1Expected), vec4(0.01))) ? 1.0 : 0.0;
5044 
5045     if (loc2Select < 0.5)
5046         result.b = all(lessThan(abs(a[2] - loc2Expected.xyz), vec3(0.01))) ? 0.5 : 0.0;
5047     else
5048         result.b = all(lessThan(abs(a_0[0] - loc2Expected), vec4(0.01))) ? 1.0 : 0.0;
5049     result.a = 1.0;
5050     color = result;
5051 })";
5052 
5053     constexpr char kFS[] = R"(varying mediump vec4 color;
5054     void main(void)
5055     {
5056         gl_FragColor = color;
5057     })";
5058 
5059     // Compile shaders.
5060     GLuint program = CompileProgram(kVS, kFS);
5061     ASSERT_NE(program, 0u);
5062 
5063     // Setup bindings.
5064     glBindAttribLocation(program, 0, "a");
5065     glBindAttribLocation(program, 0, "a_");
5066     glBindAttribLocation(program, 1, "a_1");
5067     glBindAttribLocation(program, 2, "a_0");
5068     EXPECT_GL_NO_ERROR();
5069 
5070     // Link program and get uniform locations.
5071     glLinkProgram(program);
5072     glUseProgram(program);
5073     EXPECT_GL_NO_ERROR();
5074 
5075     GLint loc0SelectLoc = glGetUniformLocation(program, "loc0Select");
5076     GLint loc1SelectLoc = glGetUniformLocation(program, "loc1Select");
5077     GLint loc2SelectLoc = glGetUniformLocation(program, "loc2Select");
5078     ASSERT_NE(-1, loc0SelectLoc);
5079     ASSERT_NE(-1, loc1SelectLoc);
5080     ASSERT_NE(-1, loc2SelectLoc);
5081     EXPECT_GL_NO_ERROR();
5082 
5083     // Set values for attributes.
5084     glVertexAttrib3f(0, 0.05, 0.1, 0.15);
5085     glVertexAttrib4f(1, 0.2, 0.25, 0.3, 0.35);
5086     glVertexAttrib4f(2, 0.4, 0.45, 0.5, 0.55);
5087     glDisableVertexAttribArray(0);
5088     glDisableVertexAttribArray(1);
5089     glDisableVertexAttribArray(2);
5090     EXPECT_GL_NO_ERROR();
5091 
5092     // Go through different combination of attributes and make sure reading through every alias is
5093     // correctly handled.
5094     GLColor expected;
5095     expected.A = 255;
5096     for (uint32_t loc0Select = 0; loc0Select < 2; ++loc0Select)
5097     {
5098         glUniform1f(loc0SelectLoc, loc0Select);
5099         expected.R = loc0Select * 127 + 127;
5100 
5101         for (uint32_t loc1Select = 0; loc1Select < 3; ++loc1Select)
5102         {
5103             glUniform1f(loc1SelectLoc, loc1Select);
5104             expected.G = loc1Select * 85 + 85;
5105 
5106             for (uint32_t loc2Select = 0; loc2Select < 2; ++loc2Select)
5107             {
5108                 glUniform1f(loc2SelectLoc, loc2Select);
5109                 expected.B = loc2Select * 127 + 127;
5110                 drawQuad(program, "position", 0.5f);
5111                 EXPECT_GL_NO_ERROR();
5112                 EXPECT_PIXEL_COLOR_NEAR(0, 0, expected, 1);
5113             }
5114         }
5115     }
5116 }
5117 
5118 // Test that a particular vertex attribute naming does not affect the functionality.
TEST_P(VertexAttributeTestES3,AttribNaming)5119 TEST_P(VertexAttributeTestES3, AttribNaming)
5120 {
5121     // http://anglebug.com/5180
5122     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
5123 
5124     // http://anglebug.com/3466
5125     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
5126 
5127     // http://anglebug.com/3467
5128     ANGLE_SKIP_TEST_IF(IsD3D());
5129 
5130     // TODO(anglebug.com/5491): iOS GLSL compiler rejects attribute aliasing.
5131     ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
5132 
5133     // This test needs roughly 16 total attributes. All backends support this except some old
5134     // Android devices.
5135     GLint maxVertexAttribs = 0;
5136     glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
5137     ANGLE_SKIP_TEST_IF(maxVertexAttribs < 16);
5138 
5139     constexpr char kVS[] = R"(#version 300 es
5140 precision mediump float;
5141 in vec4 position;
5142 in mat3 a;
5143 in mat2 a_;
5144 in vec4 a_1;
5145 in vec4 a_0;
5146 const mat3 aExpected = mat3(0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8);
5147 const mat2 a_Expected = mat2(1.0, 1.1, 1.2, 1.3);
5148 const vec4 a_1Expected = vec4(2.0, 2.1, 2.2, 2.3);
5149 const vec4 a_0Expected = vec4(3.0, 3.1, 3.2, 3.3);
5150 out mediump vec4 color;
5151 void main()
5152 {
5153     gl_Position = position;
5154 
5155     vec4 result = vec4(0);
5156     mat3 diff3 = a - aExpected;
5157     result.r = all(lessThan(abs(diff3[0]) + abs(diff3[1]) + abs(diff3[2]), vec3(0.01))) ? 1.0 : 0.0;
5158     mat2 diff2 = a_ - a_Expected;
5159     result.g = all(lessThan(abs(diff2[0]) + abs(diff2[1]), vec2(0.01))) ? 1.0 : 0.0;
5160     result.b = all(lessThan(abs(a_1 - a_1Expected), vec4(0.01))) ? 1.0 : 0.0;
5161     result.a = all(lessThan(abs(a_0 - a_0Expected), vec4(0.01))) ? 1.0 : 0.0;
5162     color = result;
5163 })";
5164 
5165     constexpr char kFS[] = R"(#version 300 es
5166 in mediump vec4 color;
5167 out mediump vec4 fragColor;
5168 void main(void)
5169 {
5170     fragColor = color;
5171 })";
5172 
5173     GLuint program = CompileProgram(kVS, kFS);
5174     ASSERT_NE(program, 0u);
5175 
5176     glBindAttribLocation(program, 0, "a");
5177     glBindAttribLocation(program, 4, "a_");
5178     glBindAttribLocation(program, 6, "a_1");
5179     glBindAttribLocation(program, 7, "a_0");
5180     EXPECT_GL_NO_ERROR();
5181 
5182     glLinkProgram(program);
5183     glUseProgram(program);
5184     EXPECT_GL_NO_ERROR();
5185 
5186     // Set values for attributes.
5187     glVertexAttrib3f(0, 0.0, 0.1, 0.2);
5188     glVertexAttrib3f(1, 0.3, 0.4, 0.5);
5189     glVertexAttrib3f(2, 0.6, 0.7, 0.8);
5190     glVertexAttrib2f(4, 1.0, 1.1);
5191     glVertexAttrib2f(5, 1.2, 1.3);
5192     glVertexAttrib4f(6, 2.0, 2.1, 2.2, 2.3);
5193     glVertexAttrib4f(7, 3.0, 3.1, 3.2, 3.3);
5194 
5195     glDisableVertexAttribArray(0);
5196     glDisableVertexAttribArray(1);
5197     glDisableVertexAttribArray(2);
5198     glDisableVertexAttribArray(3);
5199     glDisableVertexAttribArray(4);
5200     glDisableVertexAttribArray(5);
5201     glDisableVertexAttribArray(6);
5202     glDisableVertexAttribArray(7);
5203     glDisableVertexAttribArray(8);
5204     glDisableVertexAttribArray(9);
5205     EXPECT_GL_NO_ERROR();
5206 
5207     // Go through different combination of attributes and make sure reading through every alias is
5208     // correctly handled.
5209     GLColor expected{255, 255, 255, 255};
5210     drawQuad(program, "position", 0.5f);
5211     EXPECT_GL_NO_ERROR();
5212     EXPECT_PIXEL_COLOR_NEAR(0, 0, expected, 1);
5213 }
5214 
5215 // VAO emulation fails on Mac but is not used on Mac in the wild. http://anglebug.com/5577
5216 #if !defined(__APPLE__)
5217 #    define EMULATED_VAO_CONFIGS                                       \
5218         ES2_OPENGL().enable(Feature::SyncVertexArraysToDefault),       \
5219             ES2_OPENGLES().enable(Feature::SyncVertexArraysToDefault), \
5220             ES3_OPENGL().enable(Feature::SyncVertexArraysToDefault),   \
5221             ES3_OPENGLES().enable(Feature::SyncVertexArraysToDefault),
5222 #else
5223 #    define EMULATED_VAO_CONFIGS
5224 #endif
5225 
5226 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(
5227     VertexAttributeTest,
5228     ES2_VULKAN().enable(Feature::ForceFallbackFormat),
5229     ES2_VULKAN_SWIFTSHADER().enable(Feature::ForceFallbackFormat),
5230     ES3_VULKAN().enable(Feature::ForceFallbackFormat),
5231     ES3_VULKAN_SWIFTSHADER().enable(Feature::ForceFallbackFormat),
5232     ES3_METAL().disable(Feature::HasExplicitMemBarrier).disable(Feature::HasCheapRenderPass),
5233     ES3_METAL().disable(Feature::HasExplicitMemBarrier).enable(Feature::HasCheapRenderPass),
5234     ES2_OPENGL().enable(Feature::ForceMinimumMaxVertexAttributes),
5235     ES2_OPENGLES().enable(Feature::ForceMinimumMaxVertexAttributes),
5236     EMULATED_VAO_CONFIGS);
5237 
5238 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(
5239     VertexAttributeOORTest,
5240     ES2_VULKAN().enable(Feature::ForceFallbackFormat),
5241     ES2_VULKAN_SWIFTSHADER().enable(Feature::ForceFallbackFormat),
5242     ES3_VULKAN().enable(Feature::ForceFallbackFormat),
5243     ES3_VULKAN_SWIFTSHADER().enable(Feature::ForceFallbackFormat),
5244     ES3_METAL().disable(Feature::HasExplicitMemBarrier).disable(Feature::HasCheapRenderPass),
5245     ES3_METAL().disable(Feature::HasExplicitMemBarrier).enable(Feature::HasCheapRenderPass));
5246 
5247 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(RobustVertexAttributeTest);
5248 
5249 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VertexAttributeTestES3);
5250 ANGLE_INSTANTIATE_TEST_ES3_AND(
5251     VertexAttributeTestES3,
5252     ES3_VULKAN().enable(Feature::ForceFallbackFormat),
5253     ES3_VULKAN_SWIFTSHADER().enable(Feature::ForceFallbackFormat),
5254     ES3_METAL().disable(Feature::HasExplicitMemBarrier).disable(Feature::HasCheapRenderPass),
5255     ES3_METAL().disable(Feature::HasExplicitMemBarrier).enable(Feature::HasCheapRenderPass),
5256     ES3_VULKAN()
5257         .disable(Feature::UseVertexInputBindingStrideDynamicState)
5258         .disable(Feature::SupportsGraphicsPipelineLibrary));
5259 
5260 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VertexAttributeTestES31);
5261 ANGLE_INSTANTIATE_TEST_ES31_AND(VertexAttributeTestES31,
5262                                 ES31_VULKAN().enable(Feature::ForceFallbackFormat),
5263                                 ES31_VULKAN_SWIFTSHADER().enable(Feature::ForceFallbackFormat),
5264                                 ES31_VULKAN()
5265                                     .disable(Feature::UseVertexInputBindingStrideDynamicState)
5266                                     .disable(Feature::SupportsGraphicsPipelineLibrary));
5267 
5268 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(
5269     VertexAttributeCachingTest,
5270     ES2_VULKAN().enable(Feature::ForceFallbackFormat),
5271     ES2_VULKAN_SWIFTSHADER().enable(Feature::ForceFallbackFormat),
5272     ES3_VULKAN().enable(Feature::ForceFallbackFormat),
5273     ES3_VULKAN_SWIFTSHADER().enable(Feature::ForceFallbackFormat),
5274     ES3_METAL().disable(Feature::HasExplicitMemBarrier).disable(Feature::HasCheapRenderPass),
5275     ES3_METAL().disable(Feature::HasExplicitMemBarrier).enable(Feature::HasCheapRenderPass));
5276 
5277 }  // anonymous namespace
5278