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