• 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 "platform/FeaturesVk.h"
9 #include "test_utils/ANGLETest.h"
10 #include "test_utils/gl_raii.h"
11 #include "util/random_utils.h"
12 
13 using namespace angle;
14 
15 namespace
16 {
17 
TypeStride(GLenum attribType)18 GLsizei TypeStride(GLenum attribType)
19 {
20     switch (attribType)
21     {
22         case GL_UNSIGNED_BYTE:
23         case GL_BYTE:
24             return 1;
25         case GL_UNSIGNED_SHORT:
26         case GL_SHORT:
27         case GL_HALF_FLOAT:
28         case GL_HALF_FLOAT_OES:
29             return 2;
30         case GL_UNSIGNED_INT:
31         case GL_INT:
32         case GL_FLOAT:
33         case GL_UNSIGNED_INT_10_10_10_2_OES:
34         case GL_INT_10_10_10_2_OES:
35             return 4;
36         default:
37             EXPECT_TRUE(false);
38             return 0;
39     }
40 }
41 
42 template <typename T>
Normalize(T value)43 GLfloat Normalize(T value)
44 {
45     static_assert(std::is_integral<T>::value, "Integer required.");
46     if (std::is_signed<T>::value)
47     {
48         typedef typename std::make_unsigned<T>::type unsigned_type;
49         return (2.0f * static_cast<GLfloat>(value) + 1.0f) /
50                static_cast<GLfloat>(std::numeric_limits<unsigned_type>::max());
51     }
52     else
53     {
54         return static_cast<GLfloat>(value) / static_cast<GLfloat>(std::numeric_limits<T>::max());
55     }
56 }
57 
58 // Normalization for each channel of signed/unsigned 10_10_10_2 types
59 template <typename T>
Normalize10(T value)60 GLfloat Normalize10(T value)
61 {
62     static_assert(std::is_integral<T>::value, "Integer required.");
63     GLfloat floatOutput;
64     if (std::is_signed<T>::value)
65     {
66         const uint32_t signMask     = 0x200;       // 1 set at the 9th bit
67         const uint32_t negativeMask = 0xFFFFFC00;  // All bits from 10 to 31 set to 1
68 
69         if (value & signMask)
70         {
71             int negativeNumber = value | negativeMask;
72             floatOutput        = static_cast<GLfloat>(negativeNumber);
73         }
74         else
75         {
76             floatOutput = static_cast<GLfloat>(value);
77         }
78 
79         const int32_t maxValue = 0x1FF;       // 1 set in bits 0 through 8
80         const int32_t minValue = 0xFFFFFE01;  // Inverse of maxValue
81 
82         // A 10-bit two's complement number has the possibility of being minValue - 1 but
83         // OpenGL's normalization rules dictate that it should be clamped to minValue in
84         // this case.
85         if (floatOutput < minValue)
86             floatOutput = minValue;
87 
88         const int32_t halfRange = (maxValue - minValue) >> 1;
89         floatOutput             = ((floatOutput - minValue) / halfRange) - 1.0f;
90     }
91     else
92     {
93         const GLfloat maxValue = 1023.0f;  // 1 set in bits 0 through 9
94         floatOutput            = static_cast<GLfloat>(value) / maxValue;
95     }
96     return floatOutput;
97 }
98 
99 template <typename T>
Normalize2(T value)100 GLfloat Normalize2(T value)
101 {
102     static_assert(std::is_integral<T>::value, "Integer required.");
103     if (std::is_signed<T>::value)
104     {
105         GLfloat outputValue = static_cast<float>(value) / 1.0f;
106         outputValue         = (outputValue >= -1.0f) ? (outputValue) : (-1.0f);
107         return outputValue;
108     }
109     else
110     {
111         return static_cast<float>(value) / 3.0f;
112     }
113 }
114 
115 template <typename DestT, typename SrcT>
Pack1010102(std::array<SrcT,4> input)116 DestT Pack1010102(std::array<SrcT, 4> input)
117 {
118     static_assert(std::is_integral<SrcT>::value, "Integer required.");
119     static_assert(std::is_integral<DestT>::value, "Integer required.");
120     static_assert(std::is_unsigned<SrcT>::value == std::is_unsigned<DestT>::value,
121                   "Signedness should be equal.");
122     DestT rOut, gOut, bOut, aOut;
123     rOut = static_cast<DestT>(input[0]);
124     gOut = static_cast<DestT>(input[1]);
125     bOut = static_cast<DestT>(input[2]);
126     aOut = static_cast<DestT>(input[3]);
127 
128     if (std::is_unsigned<SrcT>::value)
129     {
130         return rOut << 22 | gOut << 12 | bOut << 2 | aOut;
131     }
132     else
133     {
134         // Need to apply bit mask to account for sign extension
135         return (0xFFC00000u & rOut << 22) | (0x003FF000u & gOut << 12) | (0x00000FFCu & bOut << 2) |
136                (0x00000003u & aOut);
137     }
138 }
139 
140 class VertexAttributeTest : public ANGLETest
141 {
142   protected:
VertexAttributeTest()143     VertexAttributeTest()
144         : mProgram(0), mTestAttrib(-1), mExpectedAttrib(-1), mBuffer(0), mQuadBuffer(0)
145     {
146         setWindowWidth(128);
147         setWindowHeight(128);
148         setConfigRedBits(8);
149         setConfigGreenBits(8);
150         setConfigBlueBits(8);
151         setConfigAlphaBits(8);
152         setConfigDepthBits(24);
153     }
154 
155     enum class Source
156     {
157         BUFFER,
158         IMMEDIATE,
159     };
160 
161     struct TestData final : private angle::NonCopyable
162     {
TestData__anonb060ee770111::VertexAttributeTest::TestData163         TestData(GLenum typeIn,
164                  GLboolean normalizedIn,
165                  Source sourceIn,
166                  const void *inputDataIn,
167                  const GLfloat *expectedDataIn)
168             : type(typeIn),
169               normalized(normalizedIn),
170               bufferOffset(0),
171               source(sourceIn),
172               inputData(inputDataIn),
173               expectedData(expectedDataIn)
174         {}
175 
176         GLenum type;
177         GLboolean normalized;
178         size_t bufferOffset;
179         Source source;
180 
181         const void *inputData;
182         const GLfloat *expectedData;
183     };
184 
setupTest(const TestData & test,GLint typeSize)185     void setupTest(const TestData &test, GLint typeSize)
186     {
187         if (mProgram == 0)
188         {
189             initBasicProgram();
190         }
191 
192         if (test.source == Source::BUFFER)
193         {
194             GLsizei dataSize = kVertexCount * TypeStride(test.type);
195             glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
196             glBufferData(GL_ARRAY_BUFFER, dataSize, test.inputData, GL_STATIC_DRAW);
197             glVertexAttribPointer(mTestAttrib, typeSize, test.type, test.normalized, 0,
198                                   reinterpret_cast<void *>(test.bufferOffset));
199             glBindBuffer(GL_ARRAY_BUFFER, 0);
200         }
201         else
202         {
203             ASSERT_EQ(Source::IMMEDIATE, test.source);
204             glBindBuffer(GL_ARRAY_BUFFER, 0);
205             glVertexAttribPointer(mTestAttrib, typeSize, test.type, test.normalized, 0,
206                                   test.inputData);
207         }
208 
209         glVertexAttribPointer(mExpectedAttrib, typeSize, GL_FLOAT, GL_FALSE, 0, test.expectedData);
210 
211         glEnableVertexAttribArray(mTestAttrib);
212         glEnableVertexAttribArray(mExpectedAttrib);
213     }
214 
checkPixels()215     void checkPixels() { checkRGBPixels(true); }
216 
checkRGBPixels(bool checkAlpha)217     void checkRGBPixels(bool checkAlpha)
218     {
219         GLint viewportSize[4];
220         glGetIntegerv(GL_VIEWPORT, viewportSize);
221 
222         GLint midPixelX = (viewportSize[0] + viewportSize[2]) / 2;
223         GLint midPixelY = (viewportSize[1] + viewportSize[3]) / 2;
224 
225         // We need to offset our checks from triangle edges to ensure we don't fall on a single tri
226         // Avoid making assumptions of drawQuad with four checks to check the four possible tri
227         // regions
228         if (checkAlpha)
229         {
230             EXPECT_PIXEL_EQ((midPixelX + viewportSize[0]) / 2, midPixelY, 255, 255, 255, 255);
231             EXPECT_PIXEL_EQ((midPixelX + viewportSize[2]) / 2, midPixelY, 255, 255, 255, 255);
232             EXPECT_PIXEL_EQ(midPixelX, (midPixelY + viewportSize[1]) / 2, 255, 255, 255, 255);
233             EXPECT_PIXEL_EQ(midPixelX, (midPixelY + viewportSize[3]) / 2, 255, 255, 255, 255);
234         }
235         else
236         {
237             EXPECT_PIXEL_RGB_EQUAL((midPixelX + viewportSize[0]) / 2, midPixelY, 255, 255, 255);
238             EXPECT_PIXEL_RGB_EQUAL((midPixelX + viewportSize[2]) / 2, midPixelY, 255, 255, 255);
239             EXPECT_PIXEL_RGB_EQUAL(midPixelX, (midPixelY + viewportSize[1]) / 2, 255, 255, 255);
240             EXPECT_PIXEL_RGB_EQUAL(midPixelX, (midPixelY + viewportSize[3]) / 2, 255, 255, 255);
241         }
242     }
243 
checkPixelsUnEqual()244     void checkPixelsUnEqual()
245     {
246         GLint viewportSize[4];
247         glGetIntegerv(GL_VIEWPORT, viewportSize);
248 
249         GLint midPixelX = (viewportSize[0] + viewportSize[2]) / 2;
250         GLint midPixelY = (viewportSize[1] + viewportSize[3]) / 2;
251 
252         // We need to offset our checks from triangle edges to ensure we don't fall on a single tri
253         // Avoid making assumptions of drawQuad with four checks to check the four possible tri
254         // regions
255         EXPECT_PIXEL_NE((midPixelX + viewportSize[0]) / 2, midPixelY, 255, 255, 255, 255);
256         EXPECT_PIXEL_NE((midPixelX + viewportSize[2]) / 2, midPixelY, 255, 255, 255, 255);
257         EXPECT_PIXEL_NE(midPixelX, (midPixelY + viewportSize[1]) / 2, 255, 255, 255, 255);
258         EXPECT_PIXEL_NE(midPixelX, (midPixelY + viewportSize[3]) / 2, 255, 255, 255, 255);
259     }
260 
runTest(const TestData & test)261     void runTest(const TestData &test) { runTest(test, true); }
262 
runTest(const TestData & test,bool checkPixelEqual)263     void runTest(const TestData &test, bool checkPixelEqual)
264     {
265         // TODO(geofflang): Figure out why this is broken on AMD OpenGL
266         ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
267 
268         for (GLint i = 0; i < 4; i++)
269         {
270             GLint typeSize = i + 1;
271             setupTest(test, typeSize);
272 
273             drawQuad(mProgram, "position", 0.5f);
274 
275             glDisableVertexAttribArray(mTestAttrib);
276             glDisableVertexAttribArray(mExpectedAttrib);
277 
278             if (checkPixelEqual)
279             {
280                 if ((test.type == GL_HALF_FLOAT || test.type == GL_HALF_FLOAT_OES) && IsVulkan() &&
281                     typeSize == 3)
282                 {  // We need a special case for RGB16F format on a Vulkan backend due to the fact
283                    // that in such a usecase, we need to ignore the alpha channel.
284                     checkRGBPixels(false);
285                 }
286                 else
287                 {
288                     checkPixels();
289                 }
290             }
291             else
292             {
293                 checkPixelsUnEqual();
294             }
295         }
296     }
297 
testSetUp()298     void testSetUp() override
299     {
300         glClearColor(0, 0, 0, 0);
301         glClearDepthf(0.0);
302         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
303 
304         glDisable(GL_DEPTH_TEST);
305 
306         glGenBuffers(1, &mBuffer);
307     }
308 
testTearDown()309     void testTearDown() override
310     {
311         glDeleteProgram(mProgram);
312         glDeleteBuffers(1, &mBuffer);
313         glDeleteBuffers(1, &mQuadBuffer);
314     }
315 
316     // Override a feature to force emulation of attribute formats.
overrideFeaturesVk(FeaturesVk * featuresVk)317     void overrideFeaturesVk(FeaturesVk *featuresVk) override
318     {
319         featuresVk->overrideFeatures({"force_fallback_format"}, true);
320     }
321 
compileMultiAttribProgram(GLint attribCount)322     GLuint compileMultiAttribProgram(GLint attribCount)
323     {
324         std::stringstream shaderStream;
325 
326         shaderStream << "attribute mediump vec4 position;" << std::endl;
327         for (GLint attribIndex = 0; attribIndex < attribCount; ++attribIndex)
328         {
329             shaderStream << "attribute float a" << attribIndex << ";" << std::endl;
330         }
331         shaderStream << "varying mediump float color;" << std::endl
332                      << "void main() {" << std::endl
333                      << "  gl_Position = position;" << std::endl
334                      << "  color = 0.0;" << std::endl;
335         for (GLint attribIndex = 0; attribIndex < attribCount; ++attribIndex)
336         {
337             shaderStream << "  color += a" << attribIndex << ";" << std::endl;
338         }
339         shaderStream << "}" << std::endl;
340 
341         constexpr char kFS[] =
342             "varying mediump float color;\n"
343             "void main(void)\n"
344             "{\n"
345             "    gl_FragColor = vec4(color, 0.0, 0.0, 1.0);\n"
346             "}\n";
347 
348         return CompileProgram(shaderStream.str().c_str(), kFS);
349     }
350 
setupMultiAttribs(GLuint program,GLint attribCount,GLfloat value)351     void setupMultiAttribs(GLuint program, GLint attribCount, GLfloat value)
352     {
353         glUseProgram(program);
354         for (GLint attribIndex = 0; attribIndex < attribCount; ++attribIndex)
355         {
356             std::stringstream attribStream;
357             attribStream << "a" << attribIndex;
358             GLint location = glGetAttribLocation(program, attribStream.str().c_str());
359             ASSERT_NE(-1, location);
360             glVertexAttrib1f(location, value);
361             glDisableVertexAttribArray(location);
362         }
363     }
364 
initBasicProgram()365     void initBasicProgram()
366     {
367         constexpr char kVS[] =
368             "attribute mediump vec4 position;\n"
369             "attribute mediump vec4 test;\n"
370             "attribute mediump vec4 expected;\n"
371             "varying mediump vec4 color;\n"
372             "void main(void)\n"
373             "{\n"
374             "    gl_Position = position;\n"
375             "    vec4 threshold = max(abs(expected) * 0.01, 1.0 / 64.0);\n"
376             "    color = vec4(lessThanEqual(abs(test - expected), threshold));\n"
377             "}\n";
378 
379         constexpr char kFS[] =
380             "varying mediump vec4 color;\n"
381             "void main(void)\n"
382             "{\n"
383             "    gl_FragColor = color;\n"
384             "}\n";
385 
386         mProgram = CompileProgram(kVS, kFS);
387         ASSERT_NE(0u, mProgram);
388 
389         mTestAttrib = glGetAttribLocation(mProgram, "test");
390         ASSERT_NE(-1, mTestAttrib);
391         mExpectedAttrib = glGetAttribLocation(mProgram, "expected");
392         ASSERT_NE(-1, mExpectedAttrib);
393 
394         glUseProgram(mProgram);
395     }
396 
397     static constexpr size_t kVertexCount = 24;
398 
InitTestData(std::array<GLfloat,kVertexCount> & inputData,std::array<GLfloat,kVertexCount> & expectedData)399     static void InitTestData(std::array<GLfloat, kVertexCount> &inputData,
400                              std::array<GLfloat, kVertexCount> &expectedData)
401     {
402         for (size_t count = 0; count < kVertexCount; ++count)
403         {
404             inputData[count]    = static_cast<GLfloat>(count);
405             expectedData[count] = inputData[count];
406         }
407     }
408 
409     GLuint mProgram;
410     GLint mTestAttrib;
411     GLint mExpectedAttrib;
412     GLuint mBuffer;
413     GLuint mQuadBuffer;
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 class VertexAttributeTestES3 : public VertexAttributeTest
932 {
933   protected:
VertexAttributeTestES3()934     VertexAttributeTestES3() {}
935 };
936 
TEST_P(VertexAttributeTestES3,IntUnnormalized)937 TEST_P(VertexAttributeTestES3, IntUnnormalized)
938 {
939     GLint lo                                  = std::numeric_limits<GLint>::min();
940     GLint hi                                  = std::numeric_limits<GLint>::max();
941     std::array<GLint, kVertexCount> inputData = {
942         {0, 1, 2, 3, -1, -2, -3, -4, -1, hi, hi - 1, lo, lo + 1}};
943     std::array<GLfloat, kVertexCount> expectedData;
944     for (size_t i = 0; i < kVertexCount; i++)
945     {
946         expectedData[i] = static_cast<GLfloat>(inputData[i]);
947     }
948 
949     TestData data(GL_INT, GL_FALSE, Source::BUFFER, inputData.data(), expectedData.data());
950     runTest(data);
951 }
952 
TEST_P(VertexAttributeTestES3,IntNormalized)953 TEST_P(VertexAttributeTestES3, IntNormalized)
954 {
955     GLint lo                                  = std::numeric_limits<GLint>::min();
956     GLint hi                                  = std::numeric_limits<GLint>::max();
957     std::array<GLint, kVertexCount> inputData = {
958         {0, 1, 2, 3, -1, -2, -3, -4, -1, hi, hi - 1, lo, lo + 1}};
959     std::array<GLfloat, kVertexCount> expectedData;
960     for (size_t i = 0; i < kVertexCount; i++)
961     {
962         expectedData[i] = Normalize(inputData[i]);
963     }
964 
965     TestData data(GL_INT, GL_TRUE, Source::BUFFER, inputData.data(), expectedData.data());
966     runTest(data);
967 }
968 
TEST_P(VertexAttributeTestES3,UnsignedIntUnnormalized)969 TEST_P(VertexAttributeTestES3, UnsignedIntUnnormalized)
970 {
971     GLuint mid                                 = std::numeric_limits<GLuint>::max() >> 1;
972     GLuint hi                                  = std::numeric_limits<GLuint>::max();
973     std::array<GLuint, kVertexCount> inputData = {
974         {0, 1, 2, 3, 254, 255, 256, mid - 1, mid, mid + 1, hi - 2, hi - 1, hi}};
975     std::array<GLfloat, kVertexCount> expectedData;
976     for (size_t i = 0; i < kVertexCount; i++)
977     {
978         expectedData[i] = static_cast<GLfloat>(inputData[i]);
979     }
980 
981     TestData data(GL_UNSIGNED_INT, GL_FALSE, Source::BUFFER, inputData.data(), expectedData.data());
982     runTest(data);
983 }
984 
TEST_P(VertexAttributeTestES3,UnsignedIntNormalized)985 TEST_P(VertexAttributeTestES3, UnsignedIntNormalized)
986 {
987     GLuint mid                                 = std::numeric_limits<GLuint>::max() >> 1;
988     GLuint hi                                  = std::numeric_limits<GLuint>::max();
989     std::array<GLuint, kVertexCount> inputData = {
990         {0, 1, 2, 3, 254, 255, 256, mid - 1, mid, mid + 1, hi - 2, hi - 1, hi}};
991     std::array<GLfloat, kVertexCount> expectedData;
992     for (size_t i = 0; i < kVertexCount; i++)
993     {
994         expectedData[i] = Normalize(inputData[i]);
995     }
996 
997     TestData data(GL_UNSIGNED_INT, GL_TRUE, Source::BUFFER, inputData.data(), expectedData.data());
998     runTest(data);
999 }
1000 
SetupColorsForUnitQuad(GLint location,const GLColor32F & color,GLenum usage,GLBuffer * vbo)1001 void SetupColorsForUnitQuad(GLint location, const GLColor32F &color, GLenum usage, GLBuffer *vbo)
1002 {
1003     glBindBuffer(GL_ARRAY_BUFFER, *vbo);
1004     std::vector<GLColor32F> vertices(6, color);
1005     glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLColor32F), vertices.data(), usage);
1006     glEnableVertexAttribArray(location);
1007     glVertexAttribPointer(location, 4, GL_FLOAT, GL_FALSE, 0, 0);
1008 }
1009 
1010 // Tests that rendering works as expected with VAOs.
TEST_P(VertexAttributeTestES3,VertexArrayObjectRendering)1011 TEST_P(VertexAttributeTestES3, VertexArrayObjectRendering)
1012 {
1013     constexpr char kVertexShader[] =
1014         "attribute vec4 a_position;\n"
1015         "attribute vec4 a_color;\n"
1016         "varying vec4 v_color;\n"
1017         "void main()\n"
1018         "{\n"
1019         "   gl_Position = a_position;\n"
1020         "   v_color = a_color;\n"
1021         "}";
1022 
1023     constexpr char kFragmentShader[] =
1024         "precision mediump float;\n"
1025         "varying vec4 v_color;\n"
1026         "void main()\n"
1027         "{\n"
1028         "    gl_FragColor = v_color;\n"
1029         "}";
1030 
1031     ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
1032 
1033     GLint positionLoc = glGetAttribLocation(program, "a_position");
1034     ASSERT_NE(-1, positionLoc);
1035     GLint colorLoc = glGetAttribLocation(program, "a_color");
1036     ASSERT_NE(-1, colorLoc);
1037 
1038     GLVertexArray vaos[2];
1039     GLBuffer positionBuffer;
1040     GLBuffer colorBuffers[2];
1041 
1042     const auto &quadVertices = GetQuadVertices();
1043 
1044     glBindVertexArray(vaos[0]);
1045     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
1046     glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
1047                  GL_STATIC_DRAW);
1048     glEnableVertexAttribArray(positionLoc);
1049     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
1050     SetupColorsForUnitQuad(colorLoc, kFloatRed, GL_STREAM_DRAW, &colorBuffers[0]);
1051 
1052     glBindVertexArray(vaos[1]);
1053     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
1054     glEnableVertexAttribArray(positionLoc);
1055     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
1056     SetupColorsForUnitQuad(colorLoc, kFloatGreen, GL_STATIC_DRAW, &colorBuffers[1]);
1057 
1058     glUseProgram(program);
1059     ASSERT_GL_NO_ERROR();
1060 
1061     for (int ii = 0; ii < 2; ++ii)
1062     {
1063         glBindVertexArray(vaos[0]);
1064         glDrawArrays(GL_TRIANGLES, 0, 6);
1065         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1066 
1067         glBindVertexArray(vaos[1]);
1068         glDrawArrays(GL_TRIANGLES, 0, 6);
1069         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1070     }
1071 
1072     ASSERT_GL_NO_ERROR();
1073 }
1074 
1075 // Validate that we can support GL_MAX_ATTRIBS attribs
TEST_P(VertexAttributeTest,MaxAttribs)1076 TEST_P(VertexAttributeTest, MaxAttribs)
1077 {
1078     // TODO(jmadill): Figure out why we get this error on AMD/OpenGL.
1079     ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
1080 
1081     // TODO: Support this test on Vulkan.  http://anglebug.com/2797
1082     ANGLE_SKIP_TEST_IF(IsLinux() && IsVulkan() && IsIntel());
1083 
1084     GLint maxAttribs;
1085     glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttribs);
1086     ASSERT_GL_NO_ERROR();
1087 
1088     // Reserve one attrib for position
1089     GLint drawAttribs = maxAttribs - 1;
1090 
1091     GLuint program = compileMultiAttribProgram(drawAttribs);
1092     ASSERT_NE(0u, program);
1093 
1094     setupMultiAttribs(program, drawAttribs, 0.5f / static_cast<float>(drawAttribs));
1095     drawQuad(program, "position", 0.5f);
1096 
1097     EXPECT_GL_NO_ERROR();
1098     EXPECT_PIXEL_NEAR(0, 0, 128, 0, 0, 255, 1);
1099 }
1100 
1101 // Validate that we cannot support GL_MAX_ATTRIBS+1 attribs
TEST_P(VertexAttributeTest,MaxAttribsPlusOne)1102 TEST_P(VertexAttributeTest, MaxAttribsPlusOne)
1103 {
1104     // TODO(jmadill): Figure out why we get this error on AMD/ES2/OpenGL
1105     ANGLE_SKIP_TEST_IF(IsAMD() && GetParam() == ES2_OPENGL());
1106 
1107     GLint maxAttribs;
1108     glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttribs);
1109     ASSERT_GL_NO_ERROR();
1110 
1111     // Exceed attrib count by one (counting position)
1112     GLint drawAttribs = maxAttribs;
1113 
1114     GLuint program = compileMultiAttribProgram(drawAttribs);
1115     ASSERT_EQ(0u, program);
1116 }
1117 
1118 // Simple test for when we use glBindAttribLocation
TEST_P(VertexAttributeTest,SimpleBindAttribLocation)1119 TEST_P(VertexAttributeTest, SimpleBindAttribLocation)
1120 {
1121     // Re-use the multi-attrib program, binding attribute 0
1122     GLuint program = compileMultiAttribProgram(1);
1123     glBindAttribLocation(program, 2, "position");
1124     glBindAttribLocation(program, 3, "a0");
1125     glLinkProgram(program);
1126 
1127     // Setup and draw the quad
1128     setupMultiAttribs(program, 1, 0.5f);
1129     drawQuad(program, "position", 0.5f);
1130     EXPECT_GL_NO_ERROR();
1131     EXPECT_PIXEL_NEAR(0, 0, 128, 0, 0, 255, 1);
1132 }
1133 
1134 class VertexAttributeOORTest : public VertexAttributeTest
1135 {
1136   public:
VertexAttributeOORTest()1137     VertexAttributeOORTest()
1138     {
1139         setWebGLCompatibilityEnabled(true);
1140         setRobustAccess(false);
1141     }
1142 };
1143 
1144 // Verify that drawing with a large out-of-range offset generates INVALID_OPERATION.
1145 // Requires WebGL compatibility with robust access behaviour disabled.
TEST_P(VertexAttributeOORTest,ANGLEDrawArraysBufferTooSmall)1146 TEST_P(VertexAttributeOORTest, ANGLEDrawArraysBufferTooSmall)
1147 {
1148     // Test skipped due to supporting GL_KHR_robust_buffer_access_behavior
1149     ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_KHR_robust_buffer_access_behavior"));
1150 
1151     std::array<GLfloat, kVertexCount> inputData;
1152     std::array<GLfloat, kVertexCount> expectedData;
1153     InitTestData(inputData, expectedData);
1154 
1155     TestData data(GL_FLOAT, GL_FALSE, Source::BUFFER, inputData.data(), expectedData.data());
1156     data.bufferOffset = kVertexCount * TypeStride(GL_FLOAT);
1157 
1158     setupTest(data, 1);
1159     drawQuad(mProgram, "position", 0.5f);
1160     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1161 }
1162 
1163 // Verify that index draw with an out-of-range offset generates INVALID_OPERATION.
1164 // Requires WebGL compatibility with robust access behaviour disabled.
TEST_P(VertexAttributeOORTest,ANGLEDrawElementsBufferTooSmall)1165 TEST_P(VertexAttributeOORTest, ANGLEDrawElementsBufferTooSmall)
1166 {
1167     // Test skipped due to supporting GL_KHR_robust_buffer_access_behavior
1168     ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_KHR_robust_buffer_access_behavior"));
1169 
1170     std::array<GLfloat, kVertexCount> inputData;
1171     std::array<GLfloat, kVertexCount> expectedData;
1172     InitTestData(inputData, expectedData);
1173 
1174     TestData data(GL_FLOAT, GL_FALSE, Source::BUFFER, inputData.data(), expectedData.data());
1175     data.bufferOffset = (kVertexCount - 3) * TypeStride(GL_FLOAT);
1176 
1177     setupTest(data, 1);
1178     drawIndexedQuad(mProgram, "position", 0.5f);
1179     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1180 }
1181 
1182 // Verify that DrawArarys with an out-of-range offset generates INVALID_OPERATION.
1183 // Requires WebGL compatibility with robust access behaviour disabled.
TEST_P(VertexAttributeOORTest,ANGLEDrawArraysOutOfBoundsCases)1184 TEST_P(VertexAttributeOORTest, ANGLEDrawArraysOutOfBoundsCases)
1185 {
1186     // Test skipped due to supporting GL_KHR_robust_buffer_access_behavior
1187     ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_KHR_robust_buffer_access_behavior"));
1188 
1189     initBasicProgram();
1190 
1191     GLfloat singleFloat = 1.0f;
1192     GLsizei dataSize    = TypeStride(GL_FLOAT);
1193 
1194     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1195     glBufferData(GL_ARRAY_BUFFER, dataSize, &singleFloat, GL_STATIC_DRAW);
1196     glVertexAttribPointer(mTestAttrib, 2, GL_FLOAT, GL_FALSE, 8, 0);
1197     glEnableVertexAttribArray(mTestAttrib);
1198     glBindBuffer(GL_ARRAY_BUFFER, 0);
1199 
1200     drawIndexedQuad(mProgram, "position", 0.5f);
1201     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1202 }
1203 
1204 // Verify that using a different start vertex doesn't mess up the draw.
TEST_P(VertexAttributeTest,DrawArraysWithBufferOffset)1205 TEST_P(VertexAttributeTest, DrawArraysWithBufferOffset)
1206 {
1207     // anglebug.com/4258
1208     ANGLE_SKIP_TEST_IF(IsOpenGL() && IsNVIDIA() && IsOSX());
1209 
1210     // anglebug.com/4163
1211     ANGLE_SKIP_TEST_IF(IsD3D11() && IsNVIDIA() && IsWindows7());
1212 
1213     // TODO(jmadill): Diagnose this failure.
1214     ANGLE_SKIP_TEST_IF(IsD3D11_FL93());
1215 
1216     // TODO(geofflang): Figure out why this is broken on AMD OpenGL
1217     ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
1218 
1219     // TODO(cnorthrop): Test this again on more recent drivers. http://anglebug.com/3951
1220     ANGLE_SKIP_TEST_IF(IsLinux() && IsNVIDIA() && IsVulkan());
1221 
1222     // TODO(https://anglebug.com/4269): Test is flaky on OpenGL and Metal on Mac NVIDIA.
1223     ANGLE_SKIP_TEST_IF(IsOSX() && IsNVIDIA());
1224 
1225     initBasicProgram();
1226     glUseProgram(mProgram);
1227 
1228     std::array<GLfloat, kVertexCount> inputData;
1229     std::array<GLfloat, kVertexCount> expectedData;
1230     InitTestData(inputData, expectedData);
1231 
1232     auto quadVertices        = GetQuadVertices();
1233     GLsizei quadVerticesSize = static_cast<GLsizei>(quadVertices.size() * sizeof(quadVertices[0]));
1234 
1235     glGenBuffers(1, &mQuadBuffer);
1236     glBindBuffer(GL_ARRAY_BUFFER, mQuadBuffer);
1237     glBufferData(GL_ARRAY_BUFFER, quadVerticesSize + sizeof(Vector3), nullptr, GL_STATIC_DRAW);
1238     glBufferSubData(GL_ARRAY_BUFFER, 0, quadVerticesSize, quadVertices.data());
1239 
1240     GLint positionLocation = glGetAttribLocation(mProgram, "position");
1241     ASSERT_NE(-1, positionLocation);
1242     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1243     glEnableVertexAttribArray(positionLocation);
1244 
1245     GLsizei dataSize = kVertexCount * TypeStride(GL_FLOAT);
1246     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1247     glBufferData(GL_ARRAY_BUFFER, dataSize + TypeStride(GL_FLOAT), nullptr, GL_STATIC_DRAW);
1248     glBufferSubData(GL_ARRAY_BUFFER, 0, dataSize, inputData.data());
1249     glVertexAttribPointer(mTestAttrib, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1250     glEnableVertexAttribArray(mTestAttrib);
1251 
1252     glBindBuffer(GL_ARRAY_BUFFER, 0);
1253     glVertexAttribPointer(mExpectedAttrib, 1, GL_FLOAT, GL_FALSE, 0, expectedData.data());
1254     glEnableVertexAttribArray(mExpectedAttrib);
1255 
1256     // Vertex draw with no start vertex offset (second argument is zero).
1257     glDrawArrays(GL_TRIANGLES, 0, 6);
1258     checkPixels();
1259 
1260     // Draw offset by one vertex.
1261     glDrawArrays(GL_TRIANGLES, 1, 6);
1262     checkPixels();
1263 
1264     EXPECT_GL_NO_ERROR();
1265 }
1266 
1267 // Verify that when we pass a client memory pointer to a disabled attribute the draw is still
1268 // correct.
TEST_P(VertexAttributeTest,DrawArraysWithDisabledAttribute)1269 TEST_P(VertexAttributeTest, DrawArraysWithDisabledAttribute)
1270 {
1271     initBasicProgram();
1272 
1273     std::array<GLfloat, kVertexCount> inputData;
1274     std::array<GLfloat, kVertexCount> expectedData;
1275     InitTestData(inputData, expectedData);
1276 
1277     auto quadVertices        = GetQuadVertices();
1278     GLsizei quadVerticesSize = static_cast<GLsizei>(quadVertices.size() * sizeof(quadVertices[0]));
1279 
1280     glGenBuffers(1, &mQuadBuffer);
1281     glBindBuffer(GL_ARRAY_BUFFER, mQuadBuffer);
1282     glBufferData(GL_ARRAY_BUFFER, quadVerticesSize, quadVertices.data(), GL_STATIC_DRAW);
1283 
1284     GLint positionLocation = glGetAttribLocation(mProgram, "position");
1285     ASSERT_NE(-1, positionLocation);
1286     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1287     glEnableVertexAttribArray(positionLocation);
1288 
1289     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1290     glBufferData(GL_ARRAY_BUFFER, sizeof(inputData), inputData.data(), GL_STATIC_DRAW);
1291     glVertexAttribPointer(mTestAttrib, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1292     glEnableVertexAttribArray(mTestAttrib);
1293 
1294     glBindBuffer(GL_ARRAY_BUFFER, 0);
1295     glVertexAttribPointer(mExpectedAttrib, 1, GL_FLOAT, GL_FALSE, 0, expectedData.data());
1296     glEnableVertexAttribArray(mExpectedAttrib);
1297 
1298     // mProgram2 adds an attribute 'disabled' on the basis of mProgram.
1299     constexpr char testVertexShaderSource2[] =
1300         "attribute mediump vec4 position;\n"
1301         "attribute mediump vec4 test;\n"
1302         "attribute mediump vec4 expected;\n"
1303         "attribute mediump vec4 disabled;\n"
1304         "varying mediump vec4 color;\n"
1305         "void main(void)\n"
1306         "{\n"
1307         "    gl_Position = position;\n"
1308         "    vec4 threshold = max(abs(expected + disabled) * 0.005, 1.0 / 64.0);\n"
1309         "    color = vec4(lessThanEqual(abs(test - expected), threshold));\n"
1310         "}\n";
1311 
1312     constexpr char testFragmentShaderSource[] =
1313         "varying mediump vec4 color;\n"
1314         "void main(void)\n"
1315         "{\n"
1316         "    gl_FragColor = color;\n"
1317         "}\n";
1318 
1319     ANGLE_GL_PROGRAM(program, testVertexShaderSource2, testFragmentShaderSource);
1320     GLuint mProgram2 = program.get();
1321 
1322     ASSERT_EQ(positionLocation, glGetAttribLocation(mProgram2, "position"));
1323     ASSERT_EQ(mTestAttrib, glGetAttribLocation(mProgram2, "test"));
1324     ASSERT_EQ(mExpectedAttrib, glGetAttribLocation(mProgram2, "expected"));
1325 
1326     // Pass a client memory pointer to disabledAttribute and disable it.
1327     GLint disabledAttribute = glGetAttribLocation(mProgram2, "disabled");
1328     ASSERT_EQ(-1, glGetAttribLocation(mProgram, "disabled"));
1329     glVertexAttribPointer(disabledAttribute, 1, GL_FLOAT, GL_FALSE, 0, expectedData.data());
1330     glDisableVertexAttribArray(disabledAttribute);
1331 
1332     glUseProgram(mProgram);
1333     glDrawArrays(GL_TRIANGLES, 0, 6);
1334     checkPixels();
1335 
1336     // Now enable disabledAttribute which should be used in mProgram2.
1337     glEnableVertexAttribArray(disabledAttribute);
1338     glUseProgram(mProgram2);
1339     glDrawArrays(GL_TRIANGLES, 0, 6);
1340     checkPixels();
1341 
1342     EXPECT_GL_NO_ERROR();
1343 }
1344 
1345 // Test based on WebGL Test attribs/gl-disabled-vertex-attrib.html
TEST_P(VertexAttributeTest,DisabledAttribArrays)1346 TEST_P(VertexAttributeTest, DisabledAttribArrays)
1347 {
1348     // Known failure on Retina MBP: http://crbug.com/635081
1349     ANGLE_SKIP_TEST_IF(IsOSX() && IsNVIDIA());
1350 
1351     // TODO: Support this test on Vulkan.  http://anglebug.com/2797
1352     ANGLE_SKIP_TEST_IF(IsLinux() && IsVulkan() && IsIntel());
1353 
1354     constexpr char kVS[] =
1355         "attribute vec4 a_position;\n"
1356         "attribute vec4 a_color;\n"
1357         "varying vec4 v_color;\n"
1358         "bool isCorrectColor(vec4 v) {\n"
1359         "    return v.x == 0.0 && v.y == 0.0 && v.z == 0.0 && v.w == 1.0;\n"
1360         "}"
1361         "void main() {\n"
1362         "    gl_Position = a_position;\n"
1363         "    v_color = isCorrectColor(a_color) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
1364         "}";
1365 
1366     constexpr char kFS[] =
1367         "varying mediump vec4 v_color;\n"
1368         "void main() {\n"
1369         "    gl_FragColor = v_color;\n"
1370         "}";
1371 
1372     GLint maxVertexAttribs = 0;
1373     glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
1374 
1375     for (GLint colorIndex = 0; colorIndex < maxVertexAttribs; ++colorIndex)
1376     {
1377         GLuint program = CompileProgram(kVS, kFS, [&](GLuint program) {
1378             glBindAttribLocation(program, colorIndex, "a_color");
1379         });
1380         ASSERT_NE(0u, program);
1381 
1382         drawQuad(program, "a_position", 0.5f);
1383         ASSERT_GL_NO_ERROR();
1384 
1385         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1386 
1387         glDeleteProgram(program);
1388     }
1389 }
1390 
1391 // Test that draw with offset larger than vertex attribute's stride can work
TEST_P(VertexAttributeTest,DrawWithLargeBufferOffset)1392 TEST_P(VertexAttributeTest, DrawWithLargeBufferOffset)
1393 {
1394     constexpr size_t kBufferOffset    = 10000;
1395     constexpr size_t kQuadVertexCount = 4;
1396 
1397     std::array<GLbyte, kQuadVertexCount> validInputData = {{0, 1, 2, 3}};
1398 
1399     // 4 components
1400     std::array<GLbyte, 4 *kQuadVertexCount + kBufferOffset> inputData = {};
1401 
1402     std::array<GLfloat, 4 * kQuadVertexCount> expectedData;
1403     for (size_t i = 0; i < kQuadVertexCount; i++)
1404     {
1405         for (int j = 0; j < 4; ++j)
1406         {
1407             inputData[kBufferOffset + 4 * i + j] = validInputData[i];
1408             expectedData[4 * i + j]              = validInputData[i];
1409         }
1410     }
1411 
1412     initBasicProgram();
1413 
1414     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1415     glBufferData(GL_ARRAY_BUFFER, inputData.size(), inputData.data(), GL_STATIC_DRAW);
1416     glVertexAttribPointer(mTestAttrib, 4, GL_BYTE, GL_FALSE, 0,
1417                           reinterpret_cast<const void *>(kBufferOffset));
1418     glEnableVertexAttribArray(mTestAttrib);
1419     glBindBuffer(GL_ARRAY_BUFFER, 0);
1420 
1421     glVertexAttribPointer(mExpectedAttrib, 4, GL_FLOAT, GL_FALSE, 0, expectedData.data());
1422     glEnableVertexAttribArray(mExpectedAttrib);
1423 
1424     drawIndexedQuad(mProgram, "position", 0.5f);
1425 
1426     checkPixels();
1427 }
1428 
1429 // Test that drawing with large vertex attribute pointer offset and less components than
1430 // shader expects is OK
TEST_P(VertexAttributeTest,DrawWithLargeBufferOffsetAndLessComponents)1431 TEST_P(VertexAttributeTest, DrawWithLargeBufferOffsetAndLessComponents)
1432 {
1433     // Shader expects vec4 but glVertexAttribPointer only provides 2 components
1434     constexpr char kVS[] = R"(attribute vec4 a_position;
1435 attribute vec4 a_attrib;
1436 varying vec4 v_attrib;
1437 void main()
1438 {
1439     v_attrib = a_attrib;
1440     gl_Position = a_position;
1441 })";
1442 
1443     constexpr char kFS[] = R"(precision mediump float;
1444 varying vec4 v_attrib;
1445 void main()
1446 {
1447     gl_FragColor = v_attrib;
1448 })";
1449 
1450     ANGLE_GL_PROGRAM(program, kVS, kFS);
1451     glBindAttribLocation(program, 0, "a_position");
1452     glBindAttribLocation(program, 1, "a_attrib");
1453     glLinkProgram(program);
1454     glUseProgram(program);
1455     ASSERT_GL_NO_ERROR();
1456 
1457     constexpr size_t kBufferOffset = 4998;
1458 
1459     // Set up color data so yellow is drawn (only R, G components are provided)
1460     std::vector<GLushort> data(kBufferOffset + 12);
1461     for (int i = 0; i < 12; ++i)
1462     {
1463         data[kBufferOffset + i] = 0xffff;
1464     }
1465 
1466     GLBuffer buffer;
1467     glBindBuffer(GL_ARRAY_BUFFER, buffer);
1468     glBufferData(GL_ARRAY_BUFFER, sizeof(GLushort) * data.size(), data.data(), GL_STATIC_DRAW);
1469     // Provide only 2 components for the vec4 in the shader
1470     glVertexAttribPointer(1, 2, GL_UNSIGNED_SHORT, GL_TRUE, 0,
1471                           reinterpret_cast<const void *>(sizeof(GLushort) * kBufferOffset));
1472     glBindBuffer(GL_ARRAY_BUFFER, 0);
1473     glEnableVertexAttribArray(1);
1474 
1475     drawQuad(program, "a_position", 0.5f);
1476     // Verify yellow was drawn
1477     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
1478 }
1479 
1480 class VertexAttributeTestES31 : public VertexAttributeTestES3
1481 {
1482   protected:
VertexAttributeTestES31()1483     VertexAttributeTestES31() {}
1484 
initTest()1485     void initTest()
1486     {
1487         initBasicProgram();
1488         glUseProgram(mProgram);
1489 
1490         glGenVertexArrays(1, &mVAO);
1491         glBindVertexArray(mVAO);
1492 
1493         auto quadVertices = GetQuadVertices();
1494         GLsizeiptr quadVerticesSize =
1495             static_cast<GLsizeiptr>(quadVertices.size() * sizeof(quadVertices[0]));
1496         glGenBuffers(1, &mQuadBuffer);
1497         glBindBuffer(GL_ARRAY_BUFFER, mQuadBuffer);
1498         glBufferData(GL_ARRAY_BUFFER, quadVerticesSize, quadVertices.data(), GL_STATIC_DRAW);
1499 
1500         GLint positionLocation = glGetAttribLocation(mProgram, "position");
1501         ASSERT_NE(-1, positionLocation);
1502         glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1503         glEnableVertexAttribArray(positionLocation);
1504 
1505         std::array<GLfloat, kVertexCount> expectedData;
1506         for (size_t count = 0; count < kVertexCount; ++count)
1507         {
1508             expectedData[count] = static_cast<GLfloat>(count);
1509         }
1510 
1511         const GLsizei kExpectedDataSize = kVertexCount * kFloatStride;
1512         glGenBuffers(1, &mExpectedBuffer);
1513         glBindBuffer(GL_ARRAY_BUFFER, mExpectedBuffer);
1514         glBufferData(GL_ARRAY_BUFFER, kExpectedDataSize, expectedData.data(), GL_STATIC_DRAW);
1515         glVertexAttribPointer(mExpectedAttrib, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1516         glEnableVertexAttribArray(mExpectedAttrib);
1517     }
1518 
testTearDown()1519     void testTearDown() override
1520     {
1521         VertexAttributeTestES3::testTearDown();
1522 
1523         glDeleteBuffers(1, &mExpectedBuffer);
1524         glDeleteVertexArrays(1, &mVAO);
1525     }
1526 
drawArraysWithStrideAndRelativeOffset(GLint stride,GLuint relativeOffset)1527     void drawArraysWithStrideAndRelativeOffset(GLint stride, GLuint relativeOffset)
1528     {
1529         initTest();
1530 
1531         GLint floatStride          = std::max(stride / kFloatStride, 1);
1532         GLuint floatRelativeOffset = relativeOffset / kFloatStride;
1533         size_t floatCount = static_cast<size_t>(floatRelativeOffset) + kVertexCount * floatStride;
1534         GLsizeiptr inputSize = static_cast<GLsizeiptr>(floatCount) * kFloatStride;
1535 
1536         std::vector<GLfloat> inputData(floatCount);
1537         for (size_t count = 0; count < kVertexCount; ++count)
1538         {
1539             inputData[floatRelativeOffset + count * floatStride] = static_cast<GLfloat>(count);
1540         }
1541 
1542         // Ensure inputSize, inputStride and inputOffset are multiples of TypeStride(GL_FLOAT).
1543         GLsizei inputStride            = floatStride * kFloatStride;
1544         GLsizeiptr inputRelativeOffset = floatRelativeOffset * kFloatStride;
1545         glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1546         glBufferData(GL_ARRAY_BUFFER, inputSize, nullptr, GL_STATIC_DRAW);
1547         glBufferSubData(GL_ARRAY_BUFFER, 0, inputSize, inputData.data());
1548         glVertexAttribFormat(mTestAttrib, 1, GL_FLOAT, GL_FALSE,
1549                              base::checked_cast<GLuint>(inputRelativeOffset));
1550         glBindVertexBuffer(mTestAttrib, mBuffer, 0, inputStride);
1551         glEnableVertexAttribArray(mTestAttrib);
1552 
1553         glDrawArrays(GL_TRIANGLES, 0, 6);
1554         checkPixels();
1555 
1556         EXPECT_GL_NO_ERROR();
1557     }
1558 
initOnlyUpdateBindingTest(GLint bindingToUpdate)1559     void initOnlyUpdateBindingTest(GLint bindingToUpdate)
1560     {
1561         initTest();
1562 
1563         constexpr GLuint kTestFloatOffset1                               = kVertexCount;
1564         std::array<GLfloat, kTestFloatOffset1 + kVertexCount> inputData1 = {};
1565         for (size_t count = 0; count < kVertexCount; ++count)
1566         {
1567             GLfloat value                         = static_cast<GLfloat>(count);
1568             inputData1[kTestFloatOffset1 + count] = value;
1569         }
1570 
1571         GLBuffer testBuffer1;
1572         glBindBuffer(GL_ARRAY_BUFFER, testBuffer1);
1573         glBufferData(GL_ARRAY_BUFFER, inputData1.size() * kFloatStride, inputData1.data(),
1574                      GL_STATIC_DRAW);
1575 
1576         ASSERT_NE(bindingToUpdate, mTestAttrib);
1577         ASSERT_NE(bindingToUpdate, mExpectedAttrib);
1578 
1579         // Set mTestAttrib using the binding bindingToUpdate.
1580         glVertexAttribFormat(mTestAttrib, 1, GL_FLOAT, GL_FALSE, 0);
1581         glBindVertexBuffer(bindingToUpdate, testBuffer1, kTestFloatOffset1 * kFloatStride,
1582                            kFloatStride);
1583         glVertexAttribBinding(mTestAttrib, bindingToUpdate);
1584         glEnableVertexAttribArray(mTestAttrib);
1585 
1586         // In the first draw the current VAO states are set to driver.
1587         glDrawArrays(GL_TRIANGLES, 0, 6);
1588         checkPixels();
1589         EXPECT_GL_NO_ERROR();
1590 
1591         // We need the second draw to ensure all VAO dirty bits are reset.
1592         // e.g. On D3D11 back-ends, Buffer11::resize is called in the first draw, where the related
1593         // binding is set to dirty again.
1594         glDrawArrays(GL_TRIANGLES, 0, 6);
1595         checkPixels();
1596         EXPECT_GL_NO_ERROR();
1597     }
1598 
1599     GLuint mVAO;
1600     GLuint mExpectedBuffer;
1601 
1602     const GLsizei kFloatStride = TypeStride(GL_FLOAT);
1603 
1604     // Set the maximum value for stride and relativeOffset in case they are too large.
1605     const GLint MAX_STRIDE_FOR_TEST          = 4095;
1606     const GLint MAX_RELATIVE_OFFSET_FOR_TEST = 4095;
1607 };
1608 
1609 // Verify that MAX_VERTEX_ATTRIB_STRIDE is no less than the minimum required value (2048) in ES3.1.
TEST_P(VertexAttributeTestES31,MaxVertexAttribStride)1610 TEST_P(VertexAttributeTestES31, MaxVertexAttribStride)
1611 {
1612     GLint maxStride;
1613     glGetIntegerv(GL_MAX_VERTEX_ATTRIB_STRIDE, &maxStride);
1614     ASSERT_GL_NO_ERROR();
1615 
1616     EXPECT_GE(maxStride, 2048);
1617 }
1618 
1619 // Verify that GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET is no less than the minimum required value
1620 // (2047) in ES3.1.
TEST_P(VertexAttributeTestES31,MaxVertexAttribRelativeOffset)1621 TEST_P(VertexAttributeTestES31, MaxVertexAttribRelativeOffset)
1622 {
1623     GLint maxRelativeOffset;
1624     glGetIntegerv(GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET, &maxRelativeOffset);
1625     ASSERT_GL_NO_ERROR();
1626 
1627     EXPECT_GE(maxRelativeOffset, 2047);
1628 }
1629 
1630 // Verify using MAX_VERTEX_ATTRIB_STRIDE as stride doesn't mess up the draw.
1631 // Use default value if the value of MAX_VERTEX_ATTRIB_STRIDE is too large for this test.
TEST_P(VertexAttributeTestES31,DrawArraysWithLargeStride)1632 TEST_P(VertexAttributeTestES31, DrawArraysWithLargeStride)
1633 {
1634     GLint maxStride;
1635     glGetIntegerv(GL_MAX_VERTEX_ATTRIB_STRIDE, &maxStride);
1636     ASSERT_GL_NO_ERROR();
1637 
1638     GLint largeStride = std::min(maxStride, MAX_STRIDE_FOR_TEST);
1639     drawArraysWithStrideAndRelativeOffset(largeStride, 0);
1640 }
1641 
1642 // Verify using MAX_VERTEX_ATTRIB_RELATIVE_OFFSET as relativeOffset doesn't mess up the draw.
1643 // Use default value if the value of MAX_VERTEX_ATTRIB_RELATIVE_OFFSSET is too large for this test.
TEST_P(VertexAttributeTestES31,DrawArraysWithLargeRelativeOffset)1644 TEST_P(VertexAttributeTestES31, DrawArraysWithLargeRelativeOffset)
1645 {
1646     GLint maxRelativeOffset;
1647     glGetIntegerv(GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET, &maxRelativeOffset);
1648     ASSERT_GL_NO_ERROR();
1649 
1650     GLint largeRelativeOffset = std::min(maxRelativeOffset, MAX_RELATIVE_OFFSET_FOR_TEST);
1651     drawArraysWithStrideAndRelativeOffset(0, largeRelativeOffset);
1652 }
1653 
1654 // Test that vertex array object works correctly when render pipeline and compute pipeline are
1655 // crossly executed.
TEST_P(VertexAttributeTestES31,MixedComputeAndRenderPipelines)1656 TEST_P(VertexAttributeTestES31, MixedComputeAndRenderPipelines)
1657 {
1658     constexpr char kComputeShader[] =
1659         R"(#version 310 es
1660 layout(local_size_x=1) in;
1661 void main()
1662 {
1663 })";
1664     ANGLE_GL_COMPUTE_PROGRAM(computePogram, kComputeShader);
1665 
1666     glViewport(0, 0, getWindowWidth(), getWindowHeight());
1667     glClearColor(0, 0, 0, 0);
1668 
1669     constexpr char kVertexShader[] =
1670         R"(#version 310 es
1671 precision mediump float;
1672 layout(location = 0) in vec4 position;
1673 layout(location = 2) in vec2 aOffset;
1674 layout(location = 3) in vec4 aColor;
1675 out vec4 vColor;
1676 void main() {
1677     vColor = aColor;
1678     gl_Position = position + vec4(aOffset, 0.0, 0.0);
1679 })";
1680 
1681     constexpr char kFragmentShader[] =
1682         R"(#version 310 es
1683 precision mediump float;
1684 in vec4 vColor;
1685 out vec4  color;
1686 void main() {
1687     color = vColor;
1688 })";
1689 
1690     ANGLE_GL_PROGRAM(renderProgram, kVertexShader, kFragmentShader);
1691 
1692     constexpr char kVertexShader1[] =
1693         R"(#version 310 es
1694 precision mediump float;
1695 layout(location = 1) in vec4 position;
1696 layout(location = 2) in vec2 aOffset;
1697 layout(location = 3) in vec4 aColor;
1698 out vec4 vColor;
1699 void main() {
1700     vColor = aColor;
1701     gl_Position = position + vec4(aOffset, 0.0, 0.0);
1702 })";
1703 
1704     ANGLE_GL_PROGRAM(renderProgram1, kVertexShader1, kFragmentShader);
1705 
1706     std::array<GLfloat, 8> offsets = {
1707         -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0,
1708     };
1709     GLBuffer offsetBuffer;
1710     glBindBuffer(GL_ARRAY_BUFFER, offsetBuffer);
1711     glBufferData(GL_ARRAY_BUFFER, offsets.size() * sizeof(GLfloat), offsets.data(), GL_STATIC_DRAW);
1712 
1713     std::array<GLfloat, 16> colors0 = {
1714         1.0, 0.0, 0.0, 1.0,  // Red
1715         0.0, 1.0, 0.0, 1.0,  // Green
1716         0.0, 0.0, 1.0, 1.0,  // Blue
1717         1.0, 1.0, 0.0, 1.0,  // Yellow
1718     };
1719     std::array<GLfloat, 16> colors1 = {
1720         1.0, 1.0, 0.0, 1.0,  // Yellow
1721         0.0, 0.0, 1.0, 1.0,  // Blue
1722         0.0, 1.0, 0.0, 1.0,  // Green
1723         1.0, 0.0, 0.0, 1.0,  // Red
1724     };
1725     GLBuffer colorBuffers[2];
1726     glBindBuffer(GL_ARRAY_BUFFER, colorBuffers[0]);
1727     glBufferData(GL_ARRAY_BUFFER, colors0.size() * sizeof(GLfloat), colors0.data(), GL_STATIC_DRAW);
1728     glBindBuffer(GL_ARRAY_BUFFER, colorBuffers[1]);
1729     glBufferData(GL_ARRAY_BUFFER, colors1.size() * sizeof(GLfloat), colors1.data(), GL_STATIC_DRAW);
1730 
1731     std::array<GLfloat, 16> positions = {1.0, 1.0, -1.0, 1.0,  -1.0, -1.0,
1732                                          1.0, 1.0, -1.0, -1.0, 1.0,  -1.0};
1733     GLBuffer positionBuffer;
1734     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
1735     glBufferData(GL_ARRAY_BUFFER, positions.size() * sizeof(GLfloat), positions.data(),
1736                  GL_STATIC_DRAW);
1737 
1738     const int kInstanceCount = 4;
1739     GLVertexArray vao[2];
1740     for (size_t i = 0u; i < 2u; ++i)
1741     {
1742         glBindVertexArray(vao[i]);
1743 
1744         glBindBuffer(GL_ARRAY_BUFFER, offsetBuffer);
1745         glEnableVertexAttribArray(2);
1746         glVertexAttribPointer(2, 2, GL_FLOAT, false, 0, 0);
1747         glVertexAttribDivisor(2, 1);
1748 
1749         glBindBuffer(GL_ARRAY_BUFFER, colorBuffers[i]);
1750         glEnableVertexAttribArray(3);
1751         glVertexAttribPointer(3, 4, GL_FLOAT, false, 0, 0);
1752         glVertexAttribDivisor(3, 1);
1753 
1754         glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
1755         glEnableVertexAttribArray(i);
1756         glVertexAttribPointer(i, 2, GL_FLOAT, false, 0, 0);
1757     }
1758 
1759     glClear(GL_COLOR_BUFFER_BIT);
1760 
1761     for (int i = 0; i < 3; i++)
1762     {
1763         glUseProgram(renderProgram.get());
1764         glBindVertexArray(vao[0]);
1765         glDrawArraysInstanced(GL_TRIANGLES, 0, 6, kInstanceCount);
1766 
1767         EXPECT_GL_NO_ERROR();
1768         EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 2, GLColor::red);
1769         EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::green);
1770         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1771         EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::yellow);
1772 
1773         glBindVertexArray(vao[1]);
1774         glUseProgram(computePogram.get());
1775         glDispatchCompute(1, 1, 1);
1776 
1777         glUseProgram(renderProgram1.get());
1778         glBindVertexArray(vao[1]);
1779         glDrawArraysInstanced(GL_TRIANGLES, 0, 6, kInstanceCount);
1780 
1781         EXPECT_GL_NO_ERROR();
1782         EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 2, GLColor::yellow);
1783         EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::blue);
1784         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1785         EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::red);
1786     }
1787 }
1788 
TEST_P(VertexAttributeTestES31,UseComputeShaderToUpdateVertexBuffer)1789 TEST_P(VertexAttributeTestES31, UseComputeShaderToUpdateVertexBuffer)
1790 {
1791     initTest();
1792     constexpr char kComputeShader[] =
1793         R"(#version 310 es
1794 layout(local_size_x=24) in;
1795 layout(std430, binding = 0) buffer buf {
1796     uint outData[24];
1797 };
1798 void main()
1799 {
1800     outData[gl_LocalInvocationIndex] = gl_LocalInvocationIndex;
1801 })";
1802 
1803     ANGLE_GL_COMPUTE_PROGRAM(computeProgram, kComputeShader);
1804     glUseProgram(mProgram);
1805 
1806     GLuint mid                                 = std::numeric_limits<GLuint>::max() >> 1;
1807     GLuint hi                                  = std::numeric_limits<GLuint>::max();
1808     std::array<GLuint, kVertexCount> inputData = {
1809         {0, 1, 2, 3, 254, 255, 256, mid - 1, mid, mid + 1, hi - 2, hi - 1, hi}};
1810     std::array<GLfloat, kVertexCount> expectedData;
1811     for (size_t i = 0; i < kVertexCount; i++)
1812     {
1813         expectedData[i] = Normalize(inputData[i]);
1814     }
1815 
1816     // Normalized unsigned int attribute will be classified as translated static attribute.
1817     TestData data(GL_UNSIGNED_INT, GL_TRUE, Source::BUFFER, inputData.data(), expectedData.data());
1818     GLint typeSize   = 4;
1819     GLsizei dataSize = kVertexCount * TypeStride(data.type);
1820     GLBuffer testBuffer;
1821     glBindBuffer(GL_ARRAY_BUFFER, testBuffer);
1822     glBufferData(GL_ARRAY_BUFFER, dataSize, data.inputData, GL_STATIC_DRAW);
1823     glVertexAttribPointer(mTestAttrib, typeSize, data.type, data.normalized, 0,
1824                           reinterpret_cast<void *>(data.bufferOffset));
1825     glEnableVertexAttribArray(mTestAttrib);
1826 
1827     glBindBuffer(GL_ARRAY_BUFFER, mExpectedBuffer);
1828     glBufferData(GL_ARRAY_BUFFER, dataSize, data.expectedData, GL_STATIC_DRAW);
1829     glVertexAttribPointer(mExpectedAttrib, typeSize, GL_FLOAT, GL_FALSE, 0, nullptr);
1830 
1831     // Draw twice to make sure that all static attributes dirty bits are synced.
1832     glDrawArrays(GL_TRIANGLES, 0, 6);
1833     glDrawArrays(GL_TRIANGLES, 0, 6);
1834     checkPixels();
1835 
1836     // Modify the testBuffer using a raw buffer
1837     glUseProgram(computeProgram);
1838     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, testBuffer);
1839     glDispatchCompute(1, 1, 1);
1840     glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
1841 
1842     // Draw again to verify that testBuffer has been changed.
1843     glUseProgram(mProgram);
1844     glDrawArrays(GL_TRIANGLES, 0, 6);
1845     EXPECT_GL_NO_ERROR();
1846     checkPixelsUnEqual();
1847 }
1848 
1849 // Verify that using VertexAttribBinding after VertexAttribPointer won't mess up the draw.
TEST_P(VertexAttributeTestES31,ChangeAttribBindingAfterVertexAttribPointer)1850 TEST_P(VertexAttributeTestES31, ChangeAttribBindingAfterVertexAttribPointer)
1851 {
1852     initTest();
1853 
1854     constexpr GLint kInputStride = 2;
1855     constexpr GLint kFloatOffset = 10;
1856     std::array<GLfloat, kVertexCount + kFloatOffset> inputData1;
1857     std::array<GLfloat, kVertexCount * kInputStride> inputData2;
1858     for (size_t count = 0; count < kVertexCount; ++count)
1859     {
1860         inputData1[kFloatOffset + count] = static_cast<GLfloat>(count);
1861         inputData2[count * kInputStride] = static_cast<GLfloat>(count);
1862     }
1863 
1864     GLBuffer mBuffer1;
1865     glBindBuffer(GL_ARRAY_BUFFER, mBuffer1);
1866     glBufferData(GL_ARRAY_BUFFER, inputData1.size() * kFloatStride, inputData1.data(),
1867                  GL_STATIC_DRAW);
1868     // Update the format indexed mTestAttrib and the binding indexed mTestAttrib by
1869     // VertexAttribPointer.
1870     const GLintptr kOffset = static_cast<GLintptr>(kFloatStride * kFloatOffset);
1871     glVertexAttribPointer(mTestAttrib, 1, GL_FLOAT, GL_FALSE, 0,
1872                           reinterpret_cast<const GLvoid *>(kOffset));
1873     glEnableVertexAttribArray(mTestAttrib);
1874 
1875     constexpr GLint kTestBinding = 10;
1876     ASSERT_NE(mTestAttrib, kTestBinding);
1877 
1878     GLBuffer mBuffer2;
1879     glBindBuffer(GL_ARRAY_BUFFER, mBuffer2);
1880     glBufferData(GL_ARRAY_BUFFER, inputData2.size() * kFloatStride, inputData2.data(),
1881                  GL_STATIC_DRAW);
1882     glBindVertexBuffer(kTestBinding, mBuffer2, 0, kFloatStride * kInputStride);
1883 
1884     // The attribute indexed mTestAttrib is using the binding indexed kTestBinding in the first
1885     // draw.
1886     glVertexAttribBinding(mTestAttrib, kTestBinding);
1887     glDrawArrays(GL_TRIANGLES, 0, 6);
1888     checkPixels();
1889     EXPECT_GL_NO_ERROR();
1890 
1891     // The attribute indexed mTestAttrib is using the binding indexed mTestAttrib which should be
1892     // set after the call VertexAttribPointer before the first draw.
1893     glVertexAttribBinding(mTestAttrib, mTestAttrib);
1894     glDrawArrays(GL_TRIANGLES, 0, 6);
1895     checkPixels();
1896     EXPECT_GL_NO_ERROR();
1897 }
1898 
1899 // Verify that using VertexAttribFormat after VertexAttribPointer won't mess up the draw.
TEST_P(VertexAttributeTestES31,ChangeAttribFormatAfterVertexAttribPointer)1900 TEST_P(VertexAttributeTestES31, ChangeAttribFormatAfterVertexAttribPointer)
1901 {
1902     initTest();
1903 
1904     constexpr GLuint kFloatOffset = 10;
1905     std::array<GLfloat, kVertexCount + kFloatOffset> inputData;
1906     for (size_t count = 0; count < kVertexCount; ++count)
1907     {
1908         inputData[kFloatOffset + count] = static_cast<GLfloat>(count);
1909     }
1910 
1911     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1912     glBufferData(GL_ARRAY_BUFFER, inputData.size() * kFloatStride, inputData.data(),
1913                  GL_STATIC_DRAW);
1914 
1915     // Call VertexAttribPointer on mTestAttrib. Now the relativeOffset of mTestAttrib should be 0.
1916     const GLuint kOffset = static_cast<GLuint>(kFloatStride * kFloatOffset);
1917     glVertexAttribPointer(mTestAttrib, 1, GL_FLOAT, GL_FALSE, 0, 0);
1918     glEnableVertexAttribArray(mTestAttrib);
1919 
1920     // Call VertexAttribFormat on mTestAttrib to modify the relativeOffset to kOffset.
1921     glVertexAttribFormat(mTestAttrib, 1, GL_FLOAT, GL_FALSE, kOffset);
1922 
1923     glDrawArrays(GL_TRIANGLES, 0, 6);
1924     checkPixels();
1925     EXPECT_GL_NO_ERROR();
1926 }
1927 
1928 // Verify that only updating a binding without updating the bound format won't mess up this draw.
TEST_P(VertexAttributeTestES31,OnlyUpdateBindingByBindVertexBuffer)1929 TEST_P(VertexAttributeTestES31, OnlyUpdateBindingByBindVertexBuffer)
1930 {
1931     // Default binding index for test
1932     constexpr GLint kTestBinding = 10;
1933     initOnlyUpdateBindingTest(kTestBinding);
1934 
1935     constexpr GLuint kTestFloatOffset2                               = kVertexCount * 2;
1936     std::array<GLfloat, kVertexCount> expectedData2                  = {};
1937     std::array<GLfloat, kTestFloatOffset2 + kVertexCount> inputData2 = {};
1938     for (size_t count = 0; count < kVertexCount; ++count)
1939     {
1940         GLfloat value2                        = static_cast<GLfloat>(count) * 2;
1941         expectedData2[count]                  = value2;
1942         inputData2[count + kTestFloatOffset2] = value2;
1943     }
1944 
1945     // Set another set of data for mExpectedAttrib.
1946     GLBuffer expectedBuffer2;
1947     glBindBuffer(GL_ARRAY_BUFFER, expectedBuffer2);
1948     glBufferData(GL_ARRAY_BUFFER, expectedData2.size() * kFloatStride, expectedData2.data(),
1949                  GL_STATIC_DRAW);
1950     glVertexAttribPointer(mExpectedAttrib, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1951 
1952     GLBuffer testBuffer2;
1953     glBindBuffer(GL_ARRAY_BUFFER, testBuffer2);
1954     glBufferData(GL_ARRAY_BUFFER, inputData2.size() * kFloatStride, inputData2.data(),
1955                  GL_STATIC_DRAW);
1956 
1957     // Only update the binding kTestBinding in the second draw by BindVertexBuffer.
1958     glBindVertexBuffer(kTestBinding, testBuffer2, kTestFloatOffset2 * kFloatStride, kFloatStride);
1959 
1960     glDrawArrays(GL_TRIANGLES, 0, 6);
1961     checkPixels();
1962     EXPECT_GL_NO_ERROR();
1963 }
1964 
1965 // Verify that only updating a binding without updating the bound format won't mess up this draw.
TEST_P(VertexAttributeTestES31,OnlyUpdateBindingByVertexAttribPointer)1966 TEST_P(VertexAttributeTestES31, OnlyUpdateBindingByVertexAttribPointer)
1967 {
1968     // Default binding index for test
1969     constexpr GLint kTestBinding = 10;
1970     initOnlyUpdateBindingTest(kTestBinding);
1971 
1972     constexpr GLuint kTestFloatOffset2                               = kVertexCount * 3;
1973     std::array<GLfloat, kVertexCount> expectedData2                  = {};
1974     std::array<GLfloat, kTestFloatOffset2 + kVertexCount> inputData2 = {};
1975     for (size_t count = 0; count < kVertexCount; ++count)
1976     {
1977         GLfloat value2                        = static_cast<GLfloat>(count) * 3;
1978         expectedData2[count]                  = value2;
1979         inputData2[count + kTestFloatOffset2] = value2;
1980     }
1981 
1982     // Set another set of data for mExpectedAttrib.
1983     GLBuffer expectedBuffer2;
1984     glBindBuffer(GL_ARRAY_BUFFER, expectedBuffer2);
1985     glBufferData(GL_ARRAY_BUFFER, expectedData2.size() * kFloatStride, expectedData2.data(),
1986                  GL_STATIC_DRAW);
1987     glVertexAttribPointer(mExpectedAttrib, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1988 
1989     GLBuffer testBuffer2;
1990     glBindBuffer(GL_ARRAY_BUFFER, testBuffer2);
1991     glBufferData(GL_ARRAY_BUFFER, inputData2.size() * kFloatStride, inputData2.data(),
1992                  GL_STATIC_DRAW);
1993 
1994     // Only update the binding kTestBinding in the second draw by VertexAttribPointer.
1995     glVertexAttribPointer(kTestBinding, 1, GL_FLOAT, GL_FALSE, 0,
1996                           reinterpret_cast<const void *>(kTestFloatOffset2 * kFloatStride));
1997 
1998     glDrawArrays(GL_TRIANGLES, 0, 6);
1999     checkPixels();
2000     EXPECT_GL_NO_ERROR();
2001 }
2002 
2003 class VertexAttributeCachingTest : public VertexAttributeTest
2004 {
2005   protected:
VertexAttributeCachingTest()2006     VertexAttributeCachingTest() {}
2007 
2008     void testSetUp() override;
2009 
2010     template <typename DestT>
2011     static std::vector<GLfloat> GetExpectedData(const std::vector<GLubyte> &srcData,
2012                                                 GLenum attribType,
2013                                                 GLboolean normalized);
2014 
initDoubleAttribProgram()2015     void initDoubleAttribProgram()
2016     {
2017         constexpr char kVS[] =
2018             "attribute mediump vec4 position;\n"
2019             "attribute mediump vec4 test;\n"
2020             "attribute mediump vec4 expected;\n"
2021             "attribute mediump vec4 test2;\n"
2022             "attribute mediump vec4 expected2;\n"
2023             "varying mediump vec4 color;\n"
2024             "void main(void)\n"
2025             "{\n"
2026             "    gl_Position = position;\n"
2027             "    vec4 threshold = max(abs(expected) * 0.01, 1.0 / 64.0);\n"
2028             "    color = vec4(lessThanEqual(abs(test - expected), threshold));\n"
2029             "    vec4 threshold2 = max(abs(expected2) * 0.01, 1.0 / 64.0);\n"
2030             "    color += vec4(lessThanEqual(abs(test2 - expected2), threshold2));\n"
2031             "}\n";
2032 
2033         constexpr char kFS[] =
2034             "varying mediump vec4 color;\n"
2035             "void main(void)\n"
2036             "{\n"
2037             "    gl_FragColor = color;\n"
2038             "}\n";
2039 
2040         mProgram = CompileProgram(kVS, kFS);
2041         ASSERT_NE(0u, mProgram);
2042 
2043         mTestAttrib = glGetAttribLocation(mProgram, "test");
2044         ASSERT_NE(-1, mTestAttrib);
2045         mExpectedAttrib = glGetAttribLocation(mProgram, "expected");
2046         ASSERT_NE(-1, mExpectedAttrib);
2047 
2048         glUseProgram(mProgram);
2049     }
2050 
2051     struct AttribData
2052     {
2053         AttribData(GLenum typeIn, GLint sizeIn, GLboolean normalizedIn, GLsizei strideIn);
2054 
2055         GLenum type;
2056         GLint size;
2057         GLboolean normalized;
2058         GLsizei stride;
2059     };
2060 
2061     std::vector<AttribData> mTestData;
2062     std::map<GLenum, std::vector<GLfloat>> mExpectedData;
2063     std::map<GLenum, std::vector<GLfloat>> mNormExpectedData;
2064 };
2065 
AttribData(GLenum typeIn,GLint sizeIn,GLboolean normalizedIn,GLsizei strideIn)2066 VertexAttributeCachingTest::AttribData::AttribData(GLenum typeIn,
2067                                                    GLint sizeIn,
2068                                                    GLboolean normalizedIn,
2069                                                    GLsizei strideIn)
2070     : type(typeIn), size(sizeIn), normalized(normalizedIn), stride(strideIn)
2071 {}
2072 
2073 // static
2074 template <typename DestT>
GetExpectedData(const std::vector<GLubyte> & srcData,GLenum attribType,GLboolean normalized)2075 std::vector<GLfloat> VertexAttributeCachingTest::GetExpectedData(
2076     const std::vector<GLubyte> &srcData,
2077     GLenum attribType,
2078     GLboolean normalized)
2079 {
2080     std::vector<GLfloat> expectedData;
2081 
2082     const DestT *typedSrcPtr = reinterpret_cast<const DestT *>(srcData.data());
2083     size_t iterations        = srcData.size() / TypeStride(attribType);
2084 
2085     if (normalized)
2086     {
2087         for (size_t index = 0; index < iterations; ++index)
2088         {
2089             expectedData.push_back(Normalize(typedSrcPtr[index]));
2090         }
2091     }
2092     else
2093     {
2094         for (size_t index = 0; index < iterations; ++index)
2095         {
2096             expectedData.push_back(static_cast<GLfloat>(typedSrcPtr[index]));
2097         }
2098     }
2099 
2100     return expectedData;
2101 }
2102 
testSetUp()2103 void VertexAttributeCachingTest::testSetUp()
2104 {
2105     VertexAttributeTest::testSetUp();
2106 
2107     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
2108 
2109     std::vector<GLubyte> srcData;
2110     for (size_t count = 0; count < 4; ++count)
2111     {
2112         for (GLubyte i = 0; i < std::numeric_limits<GLubyte>::max(); ++i)
2113         {
2114             srcData.push_back(i);
2115         }
2116     }
2117 
2118     glBufferData(GL_ARRAY_BUFFER, srcData.size(), srcData.data(), GL_STATIC_DRAW);
2119 
2120     GLint viewportSize[4];
2121     glGetIntegerv(GL_VIEWPORT, viewportSize);
2122 
2123     std::vector<GLenum> attribTypes;
2124     attribTypes.push_back(GL_BYTE);
2125     attribTypes.push_back(GL_UNSIGNED_BYTE);
2126     attribTypes.push_back(GL_SHORT);
2127     attribTypes.push_back(GL_UNSIGNED_SHORT);
2128 
2129     if (getClientMajorVersion() >= 3)
2130     {
2131         attribTypes.push_back(GL_INT);
2132         attribTypes.push_back(GL_UNSIGNED_INT);
2133     }
2134 
2135     constexpr GLint kMaxSize     = 4;
2136     constexpr GLsizei kMaxStride = 4;
2137 
2138     for (GLenum attribType : attribTypes)
2139     {
2140         for (GLint attribSize = 1; attribSize <= kMaxSize; ++attribSize)
2141         {
2142             for (GLsizei stride = 1; stride <= kMaxStride; ++stride)
2143             {
2144                 mTestData.push_back(AttribData(attribType, attribSize, GL_FALSE, stride));
2145                 if (attribType != GL_FLOAT)
2146                 {
2147                     mTestData.push_back(AttribData(attribType, attribSize, GL_TRUE, stride));
2148                 }
2149             }
2150         }
2151     }
2152 
2153     mExpectedData[GL_BYTE]          = GetExpectedData<GLbyte>(srcData, GL_BYTE, GL_FALSE);
2154     mExpectedData[GL_UNSIGNED_BYTE] = GetExpectedData<GLubyte>(srcData, GL_UNSIGNED_BYTE, GL_FALSE);
2155     mExpectedData[GL_SHORT]         = GetExpectedData<GLshort>(srcData, GL_SHORT, GL_FALSE);
2156     mExpectedData[GL_UNSIGNED_SHORT] =
2157         GetExpectedData<GLushort>(srcData, GL_UNSIGNED_SHORT, GL_FALSE);
2158     mExpectedData[GL_INT]          = GetExpectedData<GLint>(srcData, GL_INT, GL_FALSE);
2159     mExpectedData[GL_UNSIGNED_INT] = GetExpectedData<GLuint>(srcData, GL_UNSIGNED_INT, GL_FALSE);
2160 
2161     mNormExpectedData[GL_BYTE] = GetExpectedData<GLbyte>(srcData, GL_BYTE, GL_TRUE);
2162     mNormExpectedData[GL_UNSIGNED_BYTE] =
2163         GetExpectedData<GLubyte>(srcData, GL_UNSIGNED_BYTE, GL_TRUE);
2164     mNormExpectedData[GL_SHORT] = GetExpectedData<GLshort>(srcData, GL_SHORT, GL_TRUE);
2165     mNormExpectedData[GL_UNSIGNED_SHORT] =
2166         GetExpectedData<GLushort>(srcData, GL_UNSIGNED_SHORT, GL_TRUE);
2167     mNormExpectedData[GL_INT]          = GetExpectedData<GLint>(srcData, GL_INT, GL_TRUE);
2168     mNormExpectedData[GL_UNSIGNED_INT] = GetExpectedData<GLuint>(srcData, GL_UNSIGNED_INT, GL_TRUE);
2169 }
2170 
2171 // In D3D11, we must sometimes translate buffer data into static attribute caches. We also use a
2172 // cache management scheme which garbage collects old attributes after we start using too much
2173 // cache data. This test tries to make as many attribute caches from a single buffer as possible
2174 // to stress-test the caching code.
TEST_P(VertexAttributeCachingTest,BufferMulticaching)2175 TEST_P(VertexAttributeCachingTest, BufferMulticaching)
2176 {
2177     ANGLE_SKIP_TEST_IF(IsAMD() && IsDesktopOpenGL());
2178 
2179     initBasicProgram();
2180 
2181     glEnableVertexAttribArray(mTestAttrib);
2182     glEnableVertexAttribArray(mExpectedAttrib);
2183 
2184     ASSERT_GL_NO_ERROR();
2185 
2186     for (const AttribData &data : mTestData)
2187     {
2188         const auto &expected =
2189             (data.normalized) ? mNormExpectedData[data.type] : mExpectedData[data.type];
2190 
2191         GLsizei baseStride = static_cast<GLsizei>(data.size) * data.stride;
2192         GLsizei stride     = TypeStride(data.type) * baseStride;
2193 
2194         glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
2195         glVertexAttribPointer(mTestAttrib, data.size, data.type, data.normalized, stride, nullptr);
2196         glBindBuffer(GL_ARRAY_BUFFER, 0);
2197         glVertexAttribPointer(mExpectedAttrib, data.size, GL_FLOAT, GL_FALSE,
2198                               sizeof(GLfloat) * baseStride, expected.data());
2199         drawQuad(mProgram, "position", 0.5f);
2200         ASSERT_GL_NO_ERROR();
2201         EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::white);
2202     }
2203 }
2204 
2205 // With D3D11 dirty bits for VertxArray11, we can leave vertex state unchanged if there aren't any
2206 // GL calls that affect it. This test targets leaving one vertex attribute unchanged between draw
2207 // calls while changing another vertex attribute enough that it clears the static buffer cache
2208 // after enough iterations. It validates the unchanged attributes don't get deleted incidentally.
TEST_P(VertexAttributeCachingTest,BufferMulticachingWithOneUnchangedAttrib)2209 TEST_P(VertexAttributeCachingTest, BufferMulticachingWithOneUnchangedAttrib)
2210 {
2211     ANGLE_SKIP_TEST_IF(IsAMD() && IsDesktopOpenGL());
2212 
2213     initDoubleAttribProgram();
2214 
2215     GLint testAttrib2Location = glGetAttribLocation(mProgram, "test2");
2216     ASSERT_NE(-1, testAttrib2Location);
2217     GLint expectedAttrib2Location = glGetAttribLocation(mProgram, "expected2");
2218     ASSERT_NE(-1, expectedAttrib2Location);
2219 
2220     glEnableVertexAttribArray(mTestAttrib);
2221     glEnableVertexAttribArray(mExpectedAttrib);
2222     glEnableVertexAttribArray(testAttrib2Location);
2223     glEnableVertexAttribArray(expectedAttrib2Location);
2224 
2225     ASSERT_GL_NO_ERROR();
2226 
2227     // Use an attribute that we know must be converted. This is a bit sensitive.
2228     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
2229     glVertexAttribPointer(testAttrib2Location, 3, GL_UNSIGNED_SHORT, GL_FALSE, 6, nullptr);
2230     glBindBuffer(GL_ARRAY_BUFFER, 0);
2231     glVertexAttribPointer(expectedAttrib2Location, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3,
2232                           mExpectedData[GL_UNSIGNED_SHORT].data());
2233 
2234     for (const auto &data : mTestData)
2235     {
2236         const auto &expected =
2237             (data.normalized) ? mNormExpectedData[data.type] : mExpectedData[data.type];
2238 
2239         GLsizei baseStride = static_cast<GLsizei>(data.size) * data.stride;
2240         GLsizei stride     = TypeStride(data.type) * baseStride;
2241 
2242         glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
2243         glVertexAttribPointer(mTestAttrib, data.size, data.type, data.normalized, stride, nullptr);
2244         glBindBuffer(GL_ARRAY_BUFFER, 0);
2245         glVertexAttribPointer(mExpectedAttrib, data.size, GL_FLOAT, GL_FALSE,
2246                               sizeof(GLfloat) * baseStride, expected.data());
2247         drawQuad(mProgram, "position", 0.5f);
2248 
2249         ASSERT_GL_NO_ERROR();
2250         EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 255, 255, 255);
2251     }
2252 }
2253 
2254 // Test that if there are gaps in the attribute indices, the attributes have their correct values.
TEST_P(VertexAttributeTest,UnusedVertexAttribWorks)2255 TEST_P(VertexAttributeTest, UnusedVertexAttribWorks)
2256 {
2257     constexpr char kVertexShader[] = R"(attribute vec2 position;
2258 attribute float actualValue;
2259 uniform float expectedValue;
2260 varying float result;
2261 void main()
2262 {
2263     result = (actualValue == expectedValue) ? 1.0 : 0.0;
2264     gl_Position = vec4(position, 0, 1);
2265 })";
2266 
2267     constexpr char kFragmentShader[] = R"(varying mediump float result;
2268 void main()
2269 {
2270     gl_FragColor = result > 0.0 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
2271 })";
2272 
2273     ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
2274 
2275     // Force a gap in attributes by using location 0 and 3
2276     GLint positionLocation = 0;
2277     glBindAttribLocation(program, positionLocation, "position");
2278 
2279     GLint attribLoc = 3;
2280     glBindAttribLocation(program, attribLoc, "actualValue");
2281 
2282     // Re-link the program to update the attribute locations
2283     glLinkProgram(program);
2284     ASSERT_TRUE(CheckLinkStatusAndReturnProgram(program, true));
2285 
2286     glUseProgram(program);
2287 
2288     GLint uniLoc = glGetUniformLocation(program, "expectedValue");
2289     ASSERT_NE(-1, uniLoc);
2290 
2291     glVertexAttribPointer(attribLoc, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
2292 
2293     ASSERT_NE(-1, positionLocation);
2294     setupQuadVertexBuffer(0.5f, 1.0f);
2295     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
2296     glEnableVertexAttribArray(positionLocation);
2297 
2298     std::array<GLfloat, 4> testValues = {{1, 2, 3, 4}};
2299     for (GLfloat testValue : testValues)
2300     {
2301         glUniform1f(uniLoc, testValue);
2302         glVertexAttrib1f(attribLoc, testValue);
2303         glDrawArrays(GL_TRIANGLES, 0, 6);
2304         ASSERT_GL_NO_ERROR();
2305         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2306     }
2307 }
2308 
2309 // Tests that repeatedly updating a disabled vertex attribute works as expected.
2310 // This covers an ANGLE bug where dirty bits for current values were ignoring repeated updates.
TEST_P(VertexAttributeTest,DisabledAttribUpdates)2311 TEST_P(VertexAttributeTest, DisabledAttribUpdates)
2312 {
2313     constexpr char kVertexShader[] = R"(attribute vec2 position;
2314 attribute float actualValue;
2315 uniform float expectedValue;
2316 varying float result;
2317 void main()
2318 {
2319     result = (actualValue == expectedValue) ? 1.0 : 0.0;
2320     gl_Position = vec4(position, 0, 1);
2321 })";
2322 
2323     constexpr char kFragmentShader[] = R"(varying mediump float result;
2324 void main()
2325 {
2326     gl_FragColor = result > 0.0 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
2327 })";
2328 
2329     ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
2330 
2331     glUseProgram(program);
2332     GLint attribLoc = glGetAttribLocation(program, "actualValue");
2333     ASSERT_NE(-1, attribLoc);
2334 
2335     GLint uniLoc = glGetUniformLocation(program, "expectedValue");
2336     ASSERT_NE(-1, uniLoc);
2337 
2338     glVertexAttribPointer(attribLoc, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
2339 
2340     GLint positionLocation = glGetAttribLocation(program, "position");
2341     ASSERT_NE(-1, positionLocation);
2342     setupQuadVertexBuffer(0.5f, 1.0f);
2343     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
2344     glEnableVertexAttribArray(positionLocation);
2345 
2346     std::array<GLfloat, 4> testValues = {{1, 2, 3, 4}};
2347     for (GLfloat testValue : testValues)
2348     {
2349         glUniform1f(uniLoc, testValue);
2350         glVertexAttrib1f(attribLoc, testValue);
2351         glDrawArrays(GL_TRIANGLES, 0, 6);
2352         ASSERT_GL_NO_ERROR();
2353         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2354     }
2355 }
2356 
2357 // Test that even inactive attributes are taken into account when checking for aliasing in case the
2358 // shader version is >= 3.00. GLSL ES 3.00.6 section 12.46.
TEST_P(VertexAttributeTestES3,InactiveAttributeAliasing)2359 TEST_P(VertexAttributeTestES3, InactiveAttributeAliasing)
2360 {
2361     constexpr char vertexShader[] =
2362         R"(#version 300 es
2363         precision mediump float;
2364         in vec4 input_active;
2365         in vec4 input_unused;
2366         void main()
2367         {
2368             gl_Position = input_active;
2369         })";
2370 
2371     constexpr char fragmentShader[] =
2372         R"(#version 300 es
2373         precision mediump float;
2374         out vec4 color;
2375         void main()
2376         {
2377             color = vec4(0.0);
2378         })";
2379 
2380     ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
2381     glBindAttribLocation(program, 0, "input_active");
2382     glBindAttribLocation(program, 0, "input_unused");
2383     glLinkProgram(program);
2384     EXPECT_GL_NO_ERROR();
2385     GLint linkStatus = 0;
2386     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
2387     EXPECT_GL_FALSE(linkStatus);
2388 }
2389 
2390 // Test that enabling inactive attributes doesn't cause a crash
2391 // shader version is >= 3.00
TEST_P(VertexAttributeTestES3,EnabledButInactiveAttributes)2392 TEST_P(VertexAttributeTestES3, EnabledButInactiveAttributes)
2393 {
2394     // This is similar to runtest(), and the test is disabled there
2395     ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
2396 
2397     constexpr char testVertexShaderSource[] =
2398         R"(#version 300 es
2399 precision mediump float;
2400 in vec4 position;
2401 layout(location = 1) in vec4 test;
2402 layout(location = 2) in vec4 unused1;
2403 layout(location = 3) in vec4 unused2;
2404 layout(location = 4) in vec4 unused3;
2405 layout(location = 5) in vec4 expected;
2406 out vec4 color;
2407 void main(void)
2408 {
2409     gl_Position = position;
2410     vec4 threshold = max(abs(expected) * 0.01, 1.0 / 64.0);
2411     color = vec4(lessThanEqual(abs(test - expected), threshold));
2412 })";
2413 
2414     // Same as previous one, except it uses unused1/2 instead of test/expected, leaving unused3
2415     // unused
2416     constexpr char testVertexShader2Source[] =
2417         R"(#version 300 es
2418 precision mediump float;
2419 in vec4 position;
2420 layout(location = 1) in vec4 test;
2421 layout(location = 2) in vec4 unused1;
2422 layout(location = 3) in vec4 unused2;
2423 layout(location = 4) in vec4 unused3;
2424 layout(location = 5) in vec4 expected;
2425 out vec4 color;
2426 void main(void)
2427 {
2428     gl_Position = position;
2429     vec4 threshold = max(abs(unused2) * 0.01, 1.0 / 64.0);
2430     color = vec4(lessThanEqual(abs(unused1 - unused2), threshold));
2431 })";
2432 
2433     constexpr char testFragmentShaderSource[] =
2434         R"(#version 300 es
2435 precision mediump float;
2436 in vec4 color;
2437 out vec4 out_color;
2438 void main()
2439 {
2440     out_color = color;
2441 })";
2442 
2443     std::array<GLubyte, kVertexCount> inputData = {
2444         {0, 1, 2, 3, 4, 5, 6, 7, 125, 126, 127, 128, 129, 250, 251, 252, 253, 254, 255}};
2445     std::array<GLubyte, kVertexCount> inputData2;
2446     std::array<GLfloat, kVertexCount> expectedData;
2447     std::array<GLfloat, kVertexCount> expectedData2;
2448     for (size_t i = 0; i < kVertexCount; i++)
2449     {
2450         expectedData[i]  = inputData[i];
2451         inputData2[i]    = inputData[i] > 128 ? inputData[i] - 1 : inputData[i] + 1;
2452         expectedData2[i] = inputData2[i];
2453     }
2454 
2455     // Setup the program
2456     mProgram = CompileProgram(testVertexShaderSource, testFragmentShaderSource);
2457     ASSERT_NE(0u, mProgram);
2458 
2459     mTestAttrib = glGetAttribLocation(mProgram, "test");
2460     ASSERT_EQ(1, mTestAttrib);
2461     mExpectedAttrib = glGetAttribLocation(mProgram, "expected");
2462     ASSERT_EQ(5, mExpectedAttrib);
2463 
2464     GLint unused1Attrib = 2;
2465     GLint unused2Attrib = 3;
2466     GLint unused3Attrib = 4;
2467 
2468     // Test enabling an unused attribute before glUseProgram
2469     glEnableVertexAttribArray(unused3Attrib);
2470 
2471     glUseProgram(mProgram);
2472 
2473     // Setup the test data
2474     TestData data(GL_UNSIGNED_BYTE, GL_FALSE, Source::IMMEDIATE, inputData.data(),
2475                   expectedData.data());
2476     setupTest(data, 1);
2477 
2478     // Test enabling an unused attribute after glUseProgram
2479     glVertexAttribPointer(unused1Attrib, 1, data.type, data.normalized, 0, inputData2.data());
2480     glEnableVertexAttribArray(unused1Attrib);
2481 
2482     glVertexAttribPointer(unused2Attrib, 1, GL_FLOAT, GL_FALSE, 0, expectedData2.data());
2483     glEnableVertexAttribArray(unused2Attrib);
2484 
2485     // Run the test.  This shouldn't use the unused attributes.  Note that one of them is nullptr
2486     // which can cause a crash on certain platform-driver combination.
2487     drawQuad(mProgram, "position", 0.5f);
2488     checkPixels();
2489 
2490     // Now test with the same attributes enabled, but with a program with different attributes
2491     // active
2492     mProgram = CompileProgram(testVertexShader2Source, testFragmentShaderSource);
2493     ASSERT_NE(0u, mProgram);
2494 
2495     // Make sure all the attributes are in the same location
2496     ASSERT_EQ(glGetAttribLocation(mProgram, "unused1"), unused1Attrib);
2497     ASSERT_EQ(glGetAttribLocation(mProgram, "unused2"), unused2Attrib);
2498 
2499     glUseProgram(mProgram);
2500 
2501     // Run the test again.  unused1/2 were disabled in the previous run (as they were inactive in
2502     // the shader), but should be re-enabled now.
2503     drawQuad(mProgram, "position", 0.5f);
2504     checkPixels();
2505 }
2506 
2507 // Tests that large strides that read past the end of the buffer work correctly.
2508 // Requires ES 3.1 to query MAX_VERTEX_ATTRIB_STRIDE.
TEST_P(VertexAttributeTestES31,LargeStride)2509 TEST_P(VertexAttributeTestES31, LargeStride)
2510 {
2511     struct Vertex
2512     {
2513         Vector4 position;
2514         Vector2 color;
2515     };
2516 
2517     constexpr uint32_t kColorOffset = offsetof(Vertex, color);
2518 
2519     // Get MAX_VERTEX_ATTRIB_STRIDE.
2520     GLint maxStride;
2521     glGetIntegerv(GL_MAX_VERTEX_ATTRIB_STRIDE, &maxStride);
2522 
2523     uint32_t bufferSize  = static_cast<uint32_t>(maxStride);
2524     uint32_t stride      = sizeof(Vertex);
2525     uint32_t numVertices = bufferSize / stride;
2526 
2527     // The last vertex fits in the buffer size. The last vertex stride extends past it.
2528     ASSERT_LT(numVertices * stride, bufferSize);
2529     ASSERT_GT(numVertices * stride + kColorOffset, bufferSize);
2530 
2531     RNG rng(0);
2532 
2533     std::vector<Vertex> vertexData(bufferSize, {Vector4(), Vector2()});
2534     std::vector<GLColor> expectedColors;
2535     for (uint32_t vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex)
2536     {
2537         int x = vertexIndex % getWindowWidth();
2538         int y = vertexIndex / getWindowWidth();
2539 
2540         // Generate and clamp a 2 component vector.
2541         Vector4 randomVec4 = RandomVec4(rng.randomInt(), 0.0f, 1.0f);
2542         GLColor randomColor(randomVec4);
2543         randomColor[2]     = 0;
2544         randomColor[3]     = 255;
2545         Vector4 clampedVec = randomColor.toNormalizedVector();
2546 
2547         vertexData[vertexIndex] = {Vector4(x, y, 0.0f, 1.0f),
2548                                    Vector2(clampedVec[0], clampedVec[1])};
2549         expectedColors.push_back(randomColor);
2550     }
2551 
2552     GLBuffer buffer;
2553     glBindBuffer(GL_ARRAY_BUFFER, buffer);
2554     glBufferData(GL_ARRAY_BUFFER, bufferSize, vertexData.data(), GL_STATIC_DRAW);
2555 
2556     vertexData.resize(numVertices);
2557 
2558     constexpr char kVS[] = R"(#version 310 es
2559 in vec4 pos;
2560 in vec2 color;
2561 out vec2 vcolor;
2562 void main()
2563 {
2564     vcolor = color;
2565     gl_Position = vec4(((pos.x + 0.5) / 64.0) - 1.0, ((pos.y + 0.5) / 64.0) - 1.0, 0, 1);
2566     gl_PointSize = 1.0;
2567 })";
2568 
2569     constexpr char kFS[] = R"(#version 310 es
2570 precision mediump float;
2571 in vec2 vcolor;
2572 out vec4 fcolor;
2573 void main()
2574 {
2575     fcolor = vec4(vcolor, 0.0, 1.0);
2576 })";
2577 
2578     ANGLE_GL_PROGRAM(program, kVS, kFS);
2579     glUseProgram(program);
2580 
2581     GLint posLoc = glGetAttribLocation(program, "pos");
2582     ASSERT_NE(-1, posLoc);
2583     GLint colorLoc = glGetAttribLocation(program, "color");
2584     ASSERT_NE(-1, colorLoc);
2585 
2586     glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, stride, nullptr);
2587     glEnableVertexAttribArray(posLoc);
2588     glVertexAttribPointer(colorLoc, 2, GL_FLOAT, GL_FALSE, stride,
2589                           reinterpret_cast<GLvoid *>(kColorOffset));
2590     glEnableVertexAttribArray(colorLoc);
2591 
2592     glDrawArrays(GL_POINTS, 0, numVertices);
2593 
2594     // Validate pixels.
2595     std::vector<GLColor> actualColors(getWindowWidth() * getWindowHeight());
2596     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
2597                  actualColors.data());
2598 
2599     actualColors.resize(numVertices);
2600 
2601     ASSERT_GL_NO_ERROR();
2602     EXPECT_EQ(expectedColors, actualColors);
2603 }
2604 
2605 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
2606 // tests should be run against.
2607 // D3D11 Feature Level 9_3 uses different D3D formats for vertex attribs compared to Feature Levels
2608 // 10_0+, so we should test them separately.
2609 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(VertexAttributeTest);
2610 
2611 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(VertexAttributeOORTest);
2612 
2613 ANGLE_INSTANTIATE_TEST_ES3(VertexAttributeTestES3);
2614 
2615 ANGLE_INSTANTIATE_TEST_ES31(VertexAttributeTestES31);
2616 
2617 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(VertexAttributeCachingTest);
2618 
2619 }  // anonymous namespace
2620