xref: /aosp_15_r20/external/angle/src/tests/gl_tests/InstancingTest.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 
7*8975f5c5SAndroid Build Coastguard Worker #include "test_utils/ANGLETest.h"
8*8975f5c5SAndroid Build Coastguard Worker #include "test_utils/gl_raii.h"
9*8975f5c5SAndroid Build Coastguard Worker 
10*8975f5c5SAndroid Build Coastguard Worker using namespace angle;
11*8975f5c5SAndroid Build Coastguard Worker 
12*8975f5c5SAndroid Build Coastguard Worker namespace
13*8975f5c5SAndroid Build Coastguard Worker {
14*8975f5c5SAndroid Build Coastguard Worker enum Geometry
15*8975f5c5SAndroid Build Coastguard Worker {
16*8975f5c5SAndroid Build Coastguard Worker     Quad,
17*8975f5c5SAndroid Build Coastguard Worker     Point,
18*8975f5c5SAndroid Build Coastguard Worker     TriFan,
19*8975f5c5SAndroid Build Coastguard Worker };
20*8975f5c5SAndroid Build Coastguard Worker enum Storage
21*8975f5c5SAndroid Build Coastguard Worker {
22*8975f5c5SAndroid Build Coastguard Worker     Buffer,
23*8975f5c5SAndroid Build Coastguard Worker     Memory
24*8975f5c5SAndroid Build Coastguard Worker };
25*8975f5c5SAndroid Build Coastguard Worker enum Draw
26*8975f5c5SAndroid Build Coastguard Worker {
27*8975f5c5SAndroid Build Coastguard Worker     Indexed,
28*8975f5c5SAndroid Build Coastguard Worker     NonIndexed
29*8975f5c5SAndroid Build Coastguard Worker };
30*8975f5c5SAndroid Build Coastguard Worker enum Vendor
31*8975f5c5SAndroid Build Coastguard Worker {
32*8975f5c5SAndroid Build Coastguard Worker     Angle,
33*8975f5c5SAndroid Build Coastguard Worker     Ext
34*8975f5c5SAndroid Build Coastguard Worker };
35*8975f5c5SAndroid Build Coastguard Worker }  // namespace
36*8975f5c5SAndroid Build Coastguard Worker 
37*8975f5c5SAndroid Build Coastguard Worker class InstancingTest : public ANGLETest<>
38*8975f5c5SAndroid Build Coastguard Worker {
39*8975f5c5SAndroid Build Coastguard Worker   protected:
InstancingTest()40*8975f5c5SAndroid Build Coastguard Worker     InstancingTest()
41*8975f5c5SAndroid Build Coastguard Worker     {
42*8975f5c5SAndroid Build Coastguard Worker         setWindowWidth(256);
43*8975f5c5SAndroid Build Coastguard Worker         setWindowHeight(256);
44*8975f5c5SAndroid Build Coastguard Worker         setConfigRedBits(8);
45*8975f5c5SAndroid Build Coastguard Worker         setConfigGreenBits(8);
46*8975f5c5SAndroid Build Coastguard Worker         setConfigBlueBits(8);
47*8975f5c5SAndroid Build Coastguard Worker         setConfigAlphaBits(8);
48*8975f5c5SAndroid Build Coastguard Worker     }
49*8975f5c5SAndroid Build Coastguard Worker 
testTearDown()50*8975f5c5SAndroid Build Coastguard Worker     void testTearDown() override
51*8975f5c5SAndroid Build Coastguard Worker     {
52*8975f5c5SAndroid Build Coastguard Worker         glDeleteBuffers(1, &mInstanceBuffer);
53*8975f5c5SAndroid Build Coastguard Worker         glDeleteProgram(mProgram[0]);
54*8975f5c5SAndroid Build Coastguard Worker         glDeleteProgram(mProgram[1]);
55*8975f5c5SAndroid Build Coastguard Worker     }
56*8975f5c5SAndroid Build Coastguard Worker 
testSetUp()57*8975f5c5SAndroid Build Coastguard Worker     void testSetUp() override
58*8975f5c5SAndroid Build Coastguard Worker     {
59*8975f5c5SAndroid Build Coastguard Worker         for (unsigned i = 0; i < kMaxDrawn; ++i)
60*8975f5c5SAndroid Build Coastguard Worker         {
61*8975f5c5SAndroid Build Coastguard Worker             mInstanceData[i] = i * kDrawSize;
62*8975f5c5SAndroid Build Coastguard Worker         }
63*8975f5c5SAndroid Build Coastguard Worker         glGenBuffers(1, &mInstanceBuffer);
64*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_ARRAY_BUFFER, mInstanceBuffer);
65*8975f5c5SAndroid Build Coastguard Worker         glBufferData(GL_ARRAY_BUFFER, sizeof(mInstanceData), mInstanceData, GL_STATIC_DRAW);
66*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_ARRAY_BUFFER, 0);
67*8975f5c5SAndroid Build Coastguard Worker 
68*8975f5c5SAndroid Build Coastguard Worker         const std::string inst = "attribute float a_instance;";
69*8975f5c5SAndroid Build Coastguard Worker         const std::string pos  = "attribute vec2 a_position;";
70*8975f5c5SAndroid Build Coastguard Worker         const std::string main = R"(
71*8975f5c5SAndroid Build Coastguard Worker             void main()
72*8975f5c5SAndroid Build Coastguard Worker             {
73*8975f5c5SAndroid Build Coastguard Worker                 gl_PointSize = 6.0;
74*8975f5c5SAndroid Build Coastguard Worker                 gl_Position = vec4(a_position.x, a_position.y + a_instance, 0, 1);
75*8975f5c5SAndroid Build Coastguard Worker             }
76*8975f5c5SAndroid Build Coastguard Worker         )";
77*8975f5c5SAndroid Build Coastguard Worker 
78*8975f5c5SAndroid Build Coastguard Worker         // attrib 0 is instanced
79*8975f5c5SAndroid Build Coastguard Worker         const std::string inst0 = inst + pos + main;
80*8975f5c5SAndroid Build Coastguard Worker         mProgram[0]             = CompileProgram(inst0.c_str(), essl1_shaders::fs::Red());
81*8975f5c5SAndroid Build Coastguard Worker         ASSERT_NE(0u, mProgram[0]);
82*8975f5c5SAndroid Build Coastguard Worker         ASSERT_EQ(0, glGetAttribLocation(mProgram[0], "a_instance"));
83*8975f5c5SAndroid Build Coastguard Worker         ASSERT_EQ(1, glGetAttribLocation(mProgram[0], "a_position"));
84*8975f5c5SAndroid Build Coastguard Worker 
85*8975f5c5SAndroid Build Coastguard Worker         // attrib 1 is instanced
86*8975f5c5SAndroid Build Coastguard Worker         const std::string inst1 = pos + inst + main;
87*8975f5c5SAndroid Build Coastguard Worker         mProgram[1]             = CompileProgram(inst1.c_str(), essl1_shaders::fs::Red());
88*8975f5c5SAndroid Build Coastguard Worker         ASSERT_NE(0u, mProgram[1]);
89*8975f5c5SAndroid Build Coastguard Worker         ASSERT_EQ(1, glGetAttribLocation(mProgram[1], "a_instance"));
90*8975f5c5SAndroid Build Coastguard Worker         ASSERT_EQ(0, glGetAttribLocation(mProgram[1], "a_position"));
91*8975f5c5SAndroid Build Coastguard Worker 
92*8975f5c5SAndroid Build Coastguard Worker         glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
93*8975f5c5SAndroid Build Coastguard Worker     }
94*8975f5c5SAndroid Build Coastguard Worker 
runTest(unsigned numInstance,unsigned divisor,const int instanceAttrib,Geometry geometry,Draw draw,Storage storage,Vendor vendor,unsigned offset)95*8975f5c5SAndroid Build Coastguard Worker     void runTest(unsigned numInstance,
96*8975f5c5SAndroid Build Coastguard Worker                  unsigned divisor,
97*8975f5c5SAndroid Build Coastguard Worker                  const int instanceAttrib,  // which attrib is instanced: 0 or 1
98*8975f5c5SAndroid Build Coastguard Worker                  Geometry geometry,
99*8975f5c5SAndroid Build Coastguard Worker                  Draw draw,
100*8975f5c5SAndroid Build Coastguard Worker                  Storage storage,
101*8975f5c5SAndroid Build Coastguard Worker                  Vendor vendor,
102*8975f5c5SAndroid Build Coastguard Worker                  unsigned offset)  // for NonIndexed/DrawArrays only
103*8975f5c5SAndroid Build Coastguard Worker     {
104*8975f5c5SAndroid Build Coastguard Worker         if (vendor == Angle)
105*8975f5c5SAndroid Build Coastguard Worker         {
106*8975f5c5SAndroid Build Coastguard Worker             ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_instanced_arrays"));
107*8975f5c5SAndroid Build Coastguard Worker         }
108*8975f5c5SAndroid Build Coastguard Worker         else if (vendor == Ext)
109*8975f5c5SAndroid Build Coastguard Worker         {
110*8975f5c5SAndroid Build Coastguard Worker             ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_instanced_arrays"));
111*8975f5c5SAndroid Build Coastguard Worker         }
112*8975f5c5SAndroid Build Coastguard Worker 
113*8975f5c5SAndroid Build Coastguard Worker         // TODO: Fix these.  http://anglebug.com/42261805
114*8975f5c5SAndroid Build Coastguard Worker         ANGLE_SKIP_TEST_IF(IsD3D9() && draw == Indexed && geometry == Point);
115*8975f5c5SAndroid Build Coastguard Worker         ANGLE_SKIP_TEST_IF(IsD3D9() && IsAMD());
116*8975f5c5SAndroid Build Coastguard Worker 
117*8975f5c5SAndroid Build Coastguard Worker         // The window is divided into kMaxDrawn slices of size kDrawSize.
118*8975f5c5SAndroid Build Coastguard Worker         // The slice drawn into is determined by the instance datum.
119*8975f5c5SAndroid Build Coastguard Worker         // The instance data array selects all the slices in order.
120*8975f5c5SAndroid Build Coastguard Worker         // 'lastDrawn' is the index (zero-based) of the last slice into which we draw.
121*8975f5c5SAndroid Build Coastguard Worker         const unsigned lastDrawn = (numInstance - 1) / divisor;
122*8975f5c5SAndroid Build Coastguard Worker 
123*8975f5c5SAndroid Build Coastguard Worker         // Ensure the numInstance and divisor parameters are valid.
124*8975f5c5SAndroid Build Coastguard Worker         ASSERT_TRUE(lastDrawn < kMaxDrawn);
125*8975f5c5SAndroid Build Coastguard Worker 
126*8975f5c5SAndroid Build Coastguard Worker         ASSERT_TRUE(instanceAttrib == 0 || instanceAttrib == 1);
127*8975f5c5SAndroid Build Coastguard Worker         const int positionAttrib = 1 - instanceAttrib;
128*8975f5c5SAndroid Build Coastguard Worker 
129*8975f5c5SAndroid Build Coastguard Worker         glUseProgram(mProgram[instanceAttrib]);
130*8975f5c5SAndroid Build Coastguard Worker 
131*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_ARRAY_BUFFER, storage == Buffer ? mInstanceBuffer : 0);
132*8975f5c5SAndroid Build Coastguard Worker         glVertexAttribPointer(instanceAttrib, 1, GL_FLOAT, GL_FALSE, 0,
133*8975f5c5SAndroid Build Coastguard Worker                               storage == Buffer ? nullptr : mInstanceData);
134*8975f5c5SAndroid Build Coastguard Worker         glEnableVertexAttribArray(instanceAttrib);
135*8975f5c5SAndroid Build Coastguard Worker         if (vendor == Angle)
136*8975f5c5SAndroid Build Coastguard Worker             glVertexAttribDivisorANGLE(instanceAttrib, divisor);
137*8975f5c5SAndroid Build Coastguard Worker         else if (vendor == Ext)
138*8975f5c5SAndroid Build Coastguard Worker             glVertexAttribDivisorEXT(instanceAttrib, divisor);
139*8975f5c5SAndroid Build Coastguard Worker 
140*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_ARRAY_BUFFER, 0);
141*8975f5c5SAndroid Build Coastguard Worker         const void *vertices;
142*8975f5c5SAndroid Build Coastguard Worker         switch (geometry)
143*8975f5c5SAndroid Build Coastguard Worker         {
144*8975f5c5SAndroid Build Coastguard Worker             case Point:
145*8975f5c5SAndroid Build Coastguard Worker                 vertices = kPointVertices;
146*8975f5c5SAndroid Build Coastguard Worker                 break;
147*8975f5c5SAndroid Build Coastguard Worker             case Quad:
148*8975f5c5SAndroid Build Coastguard Worker                 vertices = kQuadVertices;
149*8975f5c5SAndroid Build Coastguard Worker                 break;
150*8975f5c5SAndroid Build Coastguard Worker             case TriFan:
151*8975f5c5SAndroid Build Coastguard Worker                 vertices = kTriFanVertices;
152*8975f5c5SAndroid Build Coastguard Worker                 break;
153*8975f5c5SAndroid Build Coastguard Worker         }
154*8975f5c5SAndroid Build Coastguard Worker         glVertexAttribPointer(positionAttrib, 2, GL_FLOAT, GL_FALSE, 0, vertices);
155*8975f5c5SAndroid Build Coastguard Worker         glEnableVertexAttribArray(positionAttrib);
156*8975f5c5SAndroid Build Coastguard Worker         if (vendor == Angle)
157*8975f5c5SAndroid Build Coastguard Worker             glVertexAttribDivisorANGLE(positionAttrib, 0);
158*8975f5c5SAndroid Build Coastguard Worker         else if (vendor == Ext)
159*8975f5c5SAndroid Build Coastguard Worker             glVertexAttribDivisorEXT(positionAttrib, 0);
160*8975f5c5SAndroid Build Coastguard Worker 
161*8975f5c5SAndroid Build Coastguard Worker         glClear(GL_COLOR_BUFFER_BIT);
162*8975f5c5SAndroid Build Coastguard Worker 
163*8975f5c5SAndroid Build Coastguard Worker         if (geometry == Point)
164*8975f5c5SAndroid Build Coastguard Worker         {
165*8975f5c5SAndroid Build Coastguard Worker             if (draw == Indexed)
166*8975f5c5SAndroid Build Coastguard Worker                 if (vendor == Angle)
167*8975f5c5SAndroid Build Coastguard Worker                     glDrawElementsInstancedANGLE(GL_POINTS, ArraySize(kPointIndices),
168*8975f5c5SAndroid Build Coastguard Worker                                                  GL_UNSIGNED_SHORT, kPointIndices, numInstance);
169*8975f5c5SAndroid Build Coastguard Worker                 else
170*8975f5c5SAndroid Build Coastguard Worker                     glDrawElementsInstancedEXT(GL_POINTS, ArraySize(kPointIndices),
171*8975f5c5SAndroid Build Coastguard Worker                                                GL_UNSIGNED_SHORT, kPointIndices, numInstance);
172*8975f5c5SAndroid Build Coastguard Worker             else if (vendor == Angle)
173*8975f5c5SAndroid Build Coastguard Worker                 glDrawArraysInstancedANGLE(GL_POINTS, offset, 4 /*vertices*/, numInstance);
174*8975f5c5SAndroid Build Coastguard Worker             else
175*8975f5c5SAndroid Build Coastguard Worker                 glDrawArraysInstancedEXT(GL_POINTS, offset, 4 /*vertices*/, numInstance);
176*8975f5c5SAndroid Build Coastguard Worker         }
177*8975f5c5SAndroid Build Coastguard Worker         else if (geometry == Quad)
178*8975f5c5SAndroid Build Coastguard Worker         {
179*8975f5c5SAndroid Build Coastguard Worker             if (draw == Indexed)
180*8975f5c5SAndroid Build Coastguard Worker                 if (vendor == Angle)
181*8975f5c5SAndroid Build Coastguard Worker                     glDrawElementsInstancedANGLE(GL_TRIANGLES, ArraySize(kQuadIndices),
182*8975f5c5SAndroid Build Coastguard Worker                                                  GL_UNSIGNED_SHORT, kQuadIndices, numInstance);
183*8975f5c5SAndroid Build Coastguard Worker                 else
184*8975f5c5SAndroid Build Coastguard Worker                     glDrawElementsInstancedEXT(GL_TRIANGLES, ArraySize(kQuadIndices),
185*8975f5c5SAndroid Build Coastguard Worker                                                GL_UNSIGNED_SHORT, kQuadIndices, numInstance);
186*8975f5c5SAndroid Build Coastguard Worker             else if (vendor == Angle)
187*8975f5c5SAndroid Build Coastguard Worker                 glDrawArraysInstancedANGLE(GL_TRIANGLES, offset, 6 /*vertices*/, numInstance);
188*8975f5c5SAndroid Build Coastguard Worker             else
189*8975f5c5SAndroid Build Coastguard Worker                 glDrawArraysInstancedEXT(GL_TRIANGLES, offset, 6 /*vertices*/, numInstance);
190*8975f5c5SAndroid Build Coastguard Worker         }
191*8975f5c5SAndroid Build Coastguard Worker         else if (geometry == TriFan)
192*8975f5c5SAndroid Build Coastguard Worker         {
193*8975f5c5SAndroid Build Coastguard Worker             if (draw == Indexed)
194*8975f5c5SAndroid Build Coastguard Worker             {
195*8975f5c5SAndroid Build Coastguard Worker                 if (storage == Buffer)
196*8975f5c5SAndroid Build Coastguard Worker                 {
197*8975f5c5SAndroid Build Coastguard Worker                     GLBuffer indexBuffer;
198*8975f5c5SAndroid Build Coastguard Worker                     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
199*8975f5c5SAndroid Build Coastguard Worker                     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kTriFanIndices), kTriFanIndices,
200*8975f5c5SAndroid Build Coastguard Worker                                  GL_STATIC_DRAW);
201*8975f5c5SAndroid Build Coastguard Worker 
202*8975f5c5SAndroid Build Coastguard Worker                     if (vendor == Angle)
203*8975f5c5SAndroid Build Coastguard Worker                         glDrawElementsInstancedANGLE(GL_TRIANGLE_FAN, ArraySize(kTriFanIndices),
204*8975f5c5SAndroid Build Coastguard Worker                                                      GL_UNSIGNED_BYTE, 0, numInstance);
205*8975f5c5SAndroid Build Coastguard Worker                     else
206*8975f5c5SAndroid Build Coastguard Worker                         glDrawElementsInstancedEXT(GL_TRIANGLE_FAN, ArraySize(kTriFanIndices),
207*8975f5c5SAndroid Build Coastguard Worker                                                    GL_UNSIGNED_BYTE, 0, numInstance);
208*8975f5c5SAndroid Build Coastguard Worker                 }
209*8975f5c5SAndroid Build Coastguard Worker                 else
210*8975f5c5SAndroid Build Coastguard Worker                 {
211*8975f5c5SAndroid Build Coastguard Worker                     if (vendor == Angle)
212*8975f5c5SAndroid Build Coastguard Worker                         glDrawElementsInstancedANGLE(GL_TRIANGLE_FAN, ArraySize(kTriFanIndices),
213*8975f5c5SAndroid Build Coastguard Worker                                                      GL_UNSIGNED_BYTE, kTriFanIndices, numInstance);
214*8975f5c5SAndroid Build Coastguard Worker                     else
215*8975f5c5SAndroid Build Coastguard Worker                         glDrawElementsInstancedEXT(GL_TRIANGLE_FAN, ArraySize(kTriFanIndices),
216*8975f5c5SAndroid Build Coastguard Worker                                                    GL_UNSIGNED_BYTE, kTriFanIndices, numInstance);
217*8975f5c5SAndroid Build Coastguard Worker                 }
218*8975f5c5SAndroid Build Coastguard Worker             }
219*8975f5c5SAndroid Build Coastguard Worker             else if (vendor == Angle)
220*8975f5c5SAndroid Build Coastguard Worker                 glDrawArraysInstancedANGLE(GL_TRIANGLE_FAN, offset, 8 /*vertices*/, numInstance);
221*8975f5c5SAndroid Build Coastguard Worker             else
222*8975f5c5SAndroid Build Coastguard Worker                 glDrawArraysInstancedEXT(GL_TRIANGLE_FAN, offset, 8 /*vertices*/, numInstance);
223*8975f5c5SAndroid Build Coastguard Worker         }
224*8975f5c5SAndroid Build Coastguard Worker 
225*8975f5c5SAndroid Build Coastguard Worker         ASSERT_GL_NO_ERROR();
226*8975f5c5SAndroid Build Coastguard Worker         checkDrawing(lastDrawn);
227*8975f5c5SAndroid Build Coastguard Worker     }
228*8975f5c5SAndroid Build Coastguard Worker 
checkDrawing(unsigned lastDrawn)229*8975f5c5SAndroid Build Coastguard Worker     void checkDrawing(unsigned lastDrawn)
230*8975f5c5SAndroid Build Coastguard Worker     {
231*8975f5c5SAndroid Build Coastguard Worker         for (unsigned i = 0; i < kMaxDrawn; ++i)
232*8975f5c5SAndroid Build Coastguard Worker         {
233*8975f5c5SAndroid Build Coastguard Worker             float y =
234*8975f5c5SAndroid Build Coastguard Worker                 -1.0f + static_cast<float>(kDrawSize) / 2.0f + static_cast<float>(i * kDrawSize);
235*8975f5c5SAndroid Build Coastguard Worker             int iy = static_cast<int>((y + 1.0f) / 2.0f * getWindowHeight());
236*8975f5c5SAndroid Build Coastguard Worker             for (unsigned j = 0; j < 8; j += 2)
237*8975f5c5SAndroid Build Coastguard Worker             {
238*8975f5c5SAndroid Build Coastguard Worker                 int ix = static_cast<int>((kPointVertices[j] + 1.0f) / 2.0f * getWindowWidth());
239*8975f5c5SAndroid Build Coastguard Worker                 EXPECT_PIXEL_COLOR_EQ(ix, iy, i <= lastDrawn ? GLColor::red : GLColor::blue)
240*8975f5c5SAndroid Build Coastguard Worker                     << std::endl;
241*8975f5c5SAndroid Build Coastguard Worker             }
242*8975f5c5SAndroid Build Coastguard Worker         }
243*8975f5c5SAndroid Build Coastguard Worker     }
244*8975f5c5SAndroid Build Coastguard Worker 
245*8975f5c5SAndroid Build Coastguard Worker     GLuint mProgram[2];
246*8975f5c5SAndroid Build Coastguard Worker     GLuint mInstanceBuffer;
247*8975f5c5SAndroid Build Coastguard Worker 
248*8975f5c5SAndroid Build Coastguard Worker     static constexpr unsigned kMaxDrawn = 16;
249*8975f5c5SAndroid Build Coastguard Worker     static constexpr float kDrawSize    = 2.0 / kMaxDrawn;
250*8975f5c5SAndroid Build Coastguard Worker     GLfloat mInstanceData[kMaxDrawn];
251*8975f5c5SAndroid Build Coastguard Worker 
252*8975f5c5SAndroid Build Coastguard Worker     // clang-format off
253*8975f5c5SAndroid Build Coastguard Worker 
254*8975f5c5SAndroid Build Coastguard Worker     // Vertices 0-5 are two triangles that form a quad filling the first "slice" of the window.
255*8975f5c5SAndroid Build Coastguard Worker     // See above about slices.  Vertices 4-9 are the same two triangles.
256*8975f5c5SAndroid Build Coastguard Worker     static constexpr GLfloat kQuadVertices[] = {
257*8975f5c5SAndroid Build Coastguard Worker         -1, -1,
258*8975f5c5SAndroid Build Coastguard Worker          1, -1,
259*8975f5c5SAndroid Build Coastguard Worker         -1, -1 + kDrawSize,
260*8975f5c5SAndroid Build Coastguard Worker          1, -1,
261*8975f5c5SAndroid Build Coastguard Worker          1, -1 + kDrawSize,
262*8975f5c5SAndroid Build Coastguard Worker         -1, -1 + kDrawSize,
263*8975f5c5SAndroid Build Coastguard Worker          1, -1,
264*8975f5c5SAndroid Build Coastguard Worker          1, -1,
265*8975f5c5SAndroid Build Coastguard Worker         -1, -1 + kDrawSize,
266*8975f5c5SAndroid Build Coastguard Worker         -1, -1,
267*8975f5c5SAndroid Build Coastguard Worker     };
268*8975f5c5SAndroid Build Coastguard Worker 
269*8975f5c5SAndroid Build Coastguard Worker     // Vertices 0-7 form a quad (triangle fan) filling the first "slice" of the window.
270*8975f5c5SAndroid Build Coastguard Worker     // Vertices 8-15 are the same.
271*8975f5c5SAndroid Build Coastguard Worker     static constexpr GLfloat kTriFanVertices[] = {
272*8975f5c5SAndroid Build Coastguard Worker         -1, -1,
273*8975f5c5SAndroid Build Coastguard Worker          1, -1,
274*8975f5c5SAndroid Build Coastguard Worker         1, -1 + 0.5f * kDrawSize,
275*8975f5c5SAndroid Build Coastguard Worker         1, -1 + kDrawSize,
276*8975f5c5SAndroid Build Coastguard Worker         0.5f, -1 + kDrawSize,
277*8975f5c5SAndroid Build Coastguard Worker         0, -1 + kDrawSize,
278*8975f5c5SAndroid Build Coastguard Worker         -0.5f, -1 + kDrawSize,
279*8975f5c5SAndroid Build Coastguard Worker         -1, -1 + kDrawSize,
280*8975f5c5SAndroid Build Coastguard Worker 
281*8975f5c5SAndroid Build Coastguard Worker         -1, -1,
282*8975f5c5SAndroid Build Coastguard Worker          1, -1,
283*8975f5c5SAndroid Build Coastguard Worker         1, -1 + 0.5f * kDrawSize,
284*8975f5c5SAndroid Build Coastguard Worker         1, -1 + kDrawSize,
285*8975f5c5SAndroid Build Coastguard Worker         0.5f, -1 + kDrawSize,
286*8975f5c5SAndroid Build Coastguard Worker         0, -1 + kDrawSize,
287*8975f5c5SAndroid Build Coastguard Worker         -0.5f, -1 + kDrawSize,
288*8975f5c5SAndroid Build Coastguard Worker         -1, -1 + kDrawSize,
289*8975f5c5SAndroid Build Coastguard Worker     };
290*8975f5c5SAndroid Build Coastguard Worker 
291*8975f5c5SAndroid Build Coastguard Worker     // Points 0-3 are spread across the first "slice."
292*8975f5c5SAndroid Build Coastguard Worker     // Points 2-4 are the same.
293*8975f5c5SAndroid Build Coastguard Worker     static constexpr GLfloat kPointVertices[] = {
294*8975f5c5SAndroid Build Coastguard Worker         -0.6f, -1 + kDrawSize / 2.0,
295*8975f5c5SAndroid Build Coastguard Worker         -0.2f, -1 + kDrawSize / 2.0,
296*8975f5c5SAndroid Build Coastguard Worker          0.2f, -1 + kDrawSize / 2.0,
297*8975f5c5SAndroid Build Coastguard Worker          0.6f, -1 + kDrawSize / 2.0,
298*8975f5c5SAndroid Build Coastguard Worker         -0.2f, -1 + kDrawSize / 2.0,
299*8975f5c5SAndroid Build Coastguard Worker         -0.6f, -1 + kDrawSize / 2.0,
300*8975f5c5SAndroid Build Coastguard Worker     };
301*8975f5c5SAndroid Build Coastguard Worker     // clang-format on
302*8975f5c5SAndroid Build Coastguard Worker 
303*8975f5c5SAndroid Build Coastguard Worker     // Same two triangles as described above.
304*8975f5c5SAndroid Build Coastguard Worker     static constexpr GLushort kQuadIndices[] = {2, 9, 7, 5, 6, 4};
305*8975f5c5SAndroid Build Coastguard Worker 
306*8975f5c5SAndroid Build Coastguard Worker     // Same triangle fan as described above.
307*8975f5c5SAndroid Build Coastguard Worker     static constexpr GLubyte kTriFanIndices[] = {0, 9, 10, 3, 4, 5, 14, 7};
308*8975f5c5SAndroid Build Coastguard Worker 
309*8975f5c5SAndroid Build Coastguard Worker     // Same four points as described above.
310*8975f5c5SAndroid Build Coastguard Worker     static constexpr GLushort kPointIndices[] = {1, 5, 3, 2};
311*8975f5c5SAndroid Build Coastguard Worker };
312*8975f5c5SAndroid Build Coastguard Worker 
313*8975f5c5SAndroid Build Coastguard Worker constexpr unsigned InstancingTest::kMaxDrawn;
314*8975f5c5SAndroid Build Coastguard Worker constexpr float InstancingTest::kDrawSize;
315*8975f5c5SAndroid Build Coastguard Worker constexpr GLfloat InstancingTest::kQuadVertices[];
316*8975f5c5SAndroid Build Coastguard Worker constexpr GLfloat InstancingTest::kTriFanVertices[];
317*8975f5c5SAndroid Build Coastguard Worker constexpr GLfloat InstancingTest::kPointVertices[];
318*8975f5c5SAndroid Build Coastguard Worker constexpr GLushort InstancingTest::kQuadIndices[];
319*8975f5c5SAndroid Build Coastguard Worker constexpr GLubyte InstancingTest::kTriFanIndices[];
320*8975f5c5SAndroid Build Coastguard Worker constexpr GLushort InstancingTest::kPointIndices[];
321*8975f5c5SAndroid Build Coastguard Worker 
322*8975f5c5SAndroid Build Coastguard Worker #define TEST_INDEXED(attrib, geometry, storage, vendor)                      \
323*8975f5c5SAndroid Build Coastguard Worker     TEST_P(InstancingTest, IndexedAttrib##attrib##geometry##storage##vendor) \
324*8975f5c5SAndroid Build Coastguard Worker     {                                                                        \
325*8975f5c5SAndroid Build Coastguard Worker         runTest(11, 2, attrib, geometry, Indexed, storage, vendor, 0);       \
326*8975f5c5SAndroid Build Coastguard Worker     }
327*8975f5c5SAndroid Build Coastguard Worker 
328*8975f5c5SAndroid Build Coastguard Worker #define TEST_NONINDEXED(attrib, geometry, storage, vendor, offset)                              \
329*8975f5c5SAndroid Build Coastguard Worker     TEST_P(InstancingTest, NonIndexedAttrib##attrib##geometry##storage##vendor##Offset##offset) \
330*8975f5c5SAndroid Build Coastguard Worker     {                                                                                           \
331*8975f5c5SAndroid Build Coastguard Worker         runTest(11, 2, attrib, geometry, NonIndexed, storage, vendor, offset);                  \
332*8975f5c5SAndroid Build Coastguard Worker     }
333*8975f5c5SAndroid Build Coastguard Worker 
334*8975f5c5SAndroid Build Coastguard Worker #define TEST_DIVISOR(numInstance, divisor)                                    \
335*8975f5c5SAndroid Build Coastguard Worker     TEST_P(InstancingTest, Instances##numInstance##Divisor##divisor)          \
336*8975f5c5SAndroid Build Coastguard Worker     {                                                                         \
337*8975f5c5SAndroid Build Coastguard Worker         runTest(numInstance, divisor, 1, Quad, NonIndexed, Buffer, Angle, 0); \
338*8975f5c5SAndroid Build Coastguard Worker     }
339*8975f5c5SAndroid Build Coastguard Worker 
340*8975f5c5SAndroid Build Coastguard Worker // D3D9 has a special codepath that rearranges the input layout sent to D3D,
341*8975f5c5SAndroid Build Coastguard Worker // to ensure that slot/stream zero of the input layout doesn't contain per-instance data, so
342*8975f5c5SAndroid Build Coastguard Worker // we test with attribute 0 being instanced, as will as attribute 1 being instanced.
343*8975f5c5SAndroid Build Coastguard Worker //
344*8975f5c5SAndroid Build Coastguard Worker // Tests with a non-zero 'offset' check that "first" parameter to glDrawArraysInstancedANGLE is only
345*8975f5c5SAndroid Build Coastguard Worker // an offset into the non-instanced vertex attributes.
346*8975f5c5SAndroid Build Coastguard Worker TEST_INDEXED(0, TriFan, Buffer, Angle)
347*8975f5c5SAndroid Build Coastguard Worker TEST_INDEXED(0, TriFan, Memory, Angle)
348*8975f5c5SAndroid Build Coastguard Worker TEST_INDEXED(1, TriFan, Buffer, Angle)
349*8975f5c5SAndroid Build Coastguard Worker TEST_INDEXED(1, TriFan, Memory, Angle)
350*8975f5c5SAndroid Build Coastguard Worker TEST_INDEXED(0, TriFan, Buffer, Ext)
351*8975f5c5SAndroid Build Coastguard Worker TEST_INDEXED(0, TriFan, Memory, Ext)
352*8975f5c5SAndroid Build Coastguard Worker TEST_INDEXED(1, TriFan, Buffer, Ext)
353*8975f5c5SAndroid Build Coastguard Worker TEST_INDEXED(1, TriFan, Memory, Ext)
354*8975f5c5SAndroid Build Coastguard Worker TEST_INDEXED(0, Quad, Buffer, Angle)
355*8975f5c5SAndroid Build Coastguard Worker TEST_INDEXED(0, Quad, Memory, Angle)
356*8975f5c5SAndroid Build Coastguard Worker TEST_INDEXED(1, Quad, Buffer, Angle)
357*8975f5c5SAndroid Build Coastguard Worker TEST_INDEXED(1, Quad, Memory, Angle)
358*8975f5c5SAndroid Build Coastguard Worker TEST_INDEXED(0, Point, Buffer, Angle)
359*8975f5c5SAndroid Build Coastguard Worker TEST_INDEXED(0, Point, Memory, Angle)
360*8975f5c5SAndroid Build Coastguard Worker TEST_INDEXED(1, Point, Buffer, Angle)
361*8975f5c5SAndroid Build Coastguard Worker TEST_INDEXED(1, Point, Memory, Angle)
362*8975f5c5SAndroid Build Coastguard Worker TEST_INDEXED(0, Quad, Buffer, Ext)
363*8975f5c5SAndroid Build Coastguard Worker TEST_INDEXED(0, Quad, Memory, Ext)
364*8975f5c5SAndroid Build Coastguard Worker TEST_INDEXED(1, Quad, Buffer, Ext)
365*8975f5c5SAndroid Build Coastguard Worker TEST_INDEXED(1, Quad, Memory, Ext)
366*8975f5c5SAndroid Build Coastguard Worker TEST_INDEXED(0, Point, Buffer, Ext)
367*8975f5c5SAndroid Build Coastguard Worker TEST_INDEXED(0, Point, Memory, Ext)
368*8975f5c5SAndroid Build Coastguard Worker TEST_INDEXED(1, Point, Buffer, Ext)
369*8975f5c5SAndroid Build Coastguard Worker TEST_INDEXED(1, Point, Memory, Ext)
370*8975f5c5SAndroid Build Coastguard Worker 
371*8975f5c5SAndroid Build Coastguard Worker // offset should be 0 or 4 for quads, 0 or 8 for triangle fan
372*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(0, TriFan, Buffer, Angle, 0)
373*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(0, TriFan, Buffer, Angle, 8)
374*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(0, TriFan, Memory, Angle, 0)
375*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(0, TriFan, Memory, Angle, 8)
376*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(1, TriFan, Buffer, Angle, 0)
377*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(1, TriFan, Buffer, Angle, 8)
378*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(1, TriFan, Memory, Angle, 0)
379*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(1, TriFan, Memory, Angle, 8)
380*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(0, TriFan, Buffer, Ext, 0)
381*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(0, TriFan, Buffer, Ext, 8)
382*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(0, TriFan, Memory, Ext, 0)
383*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(0, TriFan, Memory, Ext, 8)
384*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(1, TriFan, Buffer, Ext, 0)
385*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(1, TriFan, Buffer, Ext, 8)
386*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(1, TriFan, Memory, Ext, 0)
387*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(1, TriFan, Memory, Ext, 8)
388*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(0, Quad, Buffer, Angle, 0)
389*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(0, Quad, Buffer, Angle, 4)
390*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(0, Quad, Memory, Angle, 0)
391*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(0, Quad, Memory, Angle, 4)
392*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(1, Quad, Buffer, Angle, 0)
393*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(1, Quad, Buffer, Angle, 4)
394*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(1, Quad, Memory, Angle, 0)
395*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(1, Quad, Memory, Angle, 4)
396*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(0, Quad, Buffer, Ext, 0)
397*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(0, Quad, Buffer, Ext, 4)
398*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(0, Quad, Memory, Ext, 0)
399*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(0, Quad, Memory, Ext, 4)
400*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(1, Quad, Buffer, Ext, 0)
401*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(1, Quad, Buffer, Ext, 4)
402*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(1, Quad, Memory, Ext, 0)
403*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(1, Quad, Memory, Ext, 4)
404*8975f5c5SAndroid Build Coastguard Worker 
405*8975f5c5SAndroid Build Coastguard Worker // offset should be 0 or 2 for points
406*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(0, Point, Buffer, Angle, 0)
407*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(0, Point, Buffer, Angle, 2)
408*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(0, Point, Memory, Angle, 0)
409*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(0, Point, Memory, Angle, 2)
410*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(1, Point, Buffer, Angle, 0)
411*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(1, Point, Buffer, Angle, 2)
412*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(1, Point, Memory, Angle, 0)
413*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(1, Point, Memory, Angle, 2)
414*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(0, Point, Buffer, Ext, 0)
415*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(0, Point, Buffer, Ext, 2)
416*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(0, Point, Memory, Ext, 0)
417*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(0, Point, Memory, Ext, 2)
418*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(1, Point, Buffer, Ext, 0)
419*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(1, Point, Buffer, Ext, 2)
420*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(1, Point, Memory, Ext, 0)
421*8975f5c5SAndroid Build Coastguard Worker TEST_NONINDEXED(1, Point, Memory, Ext, 2)
422*8975f5c5SAndroid Build Coastguard Worker 
423*8975f5c5SAndroid Build Coastguard Worker // The following tests produce each value of 'lastDrawn' in runTest() from 1 to kMaxDrawn, a few
424*8975f5c5SAndroid Build Coastguard Worker // different ways.
425*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(1, 1)
426*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(1, 2)
427*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(2, 1)
428*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(3, 1)
429*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(3, 2)
430*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(4, 1)
431*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(5, 1)
432*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(5, 2)
433*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(6, 1)
434*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(6, 2)
435*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(7, 1)
436*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(7, 2)
437*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(8, 1)
438*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(8, 2)
439*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(8, 4)
440*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(9, 1)
441*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(9, 2)
442*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(10, 1)
443*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(11, 1)
444*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(11, 2)
445*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(12, 1)
446*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(12, 11)
447*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(13, 1)
448*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(13, 2)
449*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(14, 1)
450*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(15, 1)
451*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(15, 2)
452*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(16, 1)
453*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(16, 3)
454*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(16, 7)
455*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(17, 2)
456*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(20, 2)
457*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(21, 2)
458*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(23, 2)
459*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(25, 5)
460*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(25, 33)
461*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(26, 2)
462*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(26, 3)
463*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(27, 2)
464*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(27, 4)
465*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(28, 3)
466*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(29, 2)
467*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(29, 11)
468*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(30, 4)
469*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(31, 6)
470*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(32, 2)
471*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(32, 3)
472*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(32, 8)
473*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(34, 3)
474*8975f5c5SAndroid Build Coastguard Worker TEST_DIVISOR(34, 30)
475*8975f5c5SAndroid Build Coastguard Worker 
476*8975f5c5SAndroid Build Coastguard Worker // Test line loop instanced draw
TEST_P(InstancingTest,LineLoop)477*8975f5c5SAndroid Build Coastguard Worker TEST_P(InstancingTest, LineLoop)
478*8975f5c5SAndroid Build Coastguard Worker {
479*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_instanced_arrays"));
480*8975f5c5SAndroid Build Coastguard Worker 
481*8975f5c5SAndroid Build Coastguard Worker     constexpr char kVS[] = R"(
482*8975f5c5SAndroid Build Coastguard Worker attribute vec2 a_position;
483*8975f5c5SAndroid Build Coastguard Worker // x,y = offset, z = scale
484*8975f5c5SAndroid Build Coastguard Worker attribute vec3 a_transform;
485*8975f5c5SAndroid Build Coastguard Worker 
486*8975f5c5SAndroid Build Coastguard Worker attribute vec4 a_color;
487*8975f5c5SAndroid Build Coastguard Worker 
488*8975f5c5SAndroid Build Coastguard Worker varying vec4 v_color;
489*8975f5c5SAndroid Build Coastguard Worker 
490*8975f5c5SAndroid Build Coastguard Worker invariant gl_Position;
491*8975f5c5SAndroid Build Coastguard Worker void main()
492*8975f5c5SAndroid Build Coastguard Worker {
493*8975f5c5SAndroid Build Coastguard Worker     vec2 v_position = a_transform.z * a_position + a_transform.xy;
494*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(v_position, 0.0, 1.0);
495*8975f5c5SAndroid Build Coastguard Worker 
496*8975f5c5SAndroid Build Coastguard Worker     v_color = a_color;
497*8975f5c5SAndroid Build Coastguard Worker })";
498*8975f5c5SAndroid Build Coastguard Worker 
499*8975f5c5SAndroid Build Coastguard Worker     constexpr char kFS[] = R"(
500*8975f5c5SAndroid Build Coastguard Worker precision highp float;
501*8975f5c5SAndroid Build Coastguard Worker varying vec4 v_color;
502*8975f5c5SAndroid Build Coastguard Worker void main()
503*8975f5c5SAndroid Build Coastguard Worker {
504*8975f5c5SAndroid Build Coastguard Worker     gl_FragColor = v_color;
505*8975f5c5SAndroid Build Coastguard Worker })";
506*8975f5c5SAndroid Build Coastguard Worker 
507*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(program, kVS, kFS);
508*8975f5c5SAndroid Build Coastguard Worker     glBindAttribLocation(program, 0, "a_position");
509*8975f5c5SAndroid Build Coastguard Worker     glBindAttribLocation(program, 1, "a_transform");
510*8975f5c5SAndroid Build Coastguard Worker     glBindAttribLocation(program, 2, "a_color");
511*8975f5c5SAndroid Build Coastguard Worker     glLinkProgram(program);
512*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
513*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
514*8975f5c5SAndroid Build Coastguard Worker 
515*8975f5c5SAndroid Build Coastguard Worker     constexpr GLfloat vertices[] = {
516*8975f5c5SAndroid Build Coastguard Worker         0.1, 0.1, -0.1, 0.1, -0.1, -0.1, 0.1, -0.1,
517*8975f5c5SAndroid Build Coastguard Worker     };
518*8975f5c5SAndroid Build Coastguard Worker 
519*8975f5c5SAndroid Build Coastguard Worker     constexpr GLfloat transform[] = {
520*8975f5c5SAndroid Build Coastguard Worker         0, 0, 9, 0.2, 0.1, 2, 0.5, -0.2, 3, -0.8, -0.5, 1, -0.4, 0.4, 6,
521*8975f5c5SAndroid Build Coastguard Worker     };
522*8975f5c5SAndroid Build Coastguard Worker 
523*8975f5c5SAndroid Build Coastguard Worker     constexpr GLsizei instances = ArraySize(transform) / 3;
524*8975f5c5SAndroid Build Coastguard Worker 
525*8975f5c5SAndroid Build Coastguard Worker     const GLfloat colors[instances * 3] = {
526*8975f5c5SAndroid Build Coastguard Worker         1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0,
527*8975f5c5SAndroid Build Coastguard Worker     };
528*8975f5c5SAndroid Build Coastguard Worker 
529*8975f5c5SAndroid Build Coastguard Worker     constexpr GLushort lineloopAsStripIndices[] = {0, 1, 2, 3, 0};
530*8975f5c5SAndroid Build Coastguard Worker 
531*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLColor> expectedPixels(getWindowWidth() * getWindowHeight());
532*8975f5c5SAndroid Build Coastguard Worker 
533*8975f5c5SAndroid Build Coastguard Worker     // Draw in non-instanced way
534*8975f5c5SAndroid Build Coastguard Worker     glClearColor(0, 0, 0, 1);
535*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
536*8975f5c5SAndroid Build Coastguard Worker 
537*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(0);
538*8975f5c5SAndroid Build Coastguard Worker     glDisableVertexAttribArray(1);
539*8975f5c5SAndroid Build Coastguard Worker 
540*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribDivisorANGLE(0, 0);
541*8975f5c5SAndroid Build Coastguard Worker 
542*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, 0);
543*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
544*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
545*8975f5c5SAndroid Build Coastguard Worker 
546*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0; i < instances; ++i)
547*8975f5c5SAndroid Build Coastguard Worker     {
548*8975f5c5SAndroid Build Coastguard Worker         glVertexAttrib3fv(1, transform + 3 * i);
549*8975f5c5SAndroid Build Coastguard Worker         glVertexAttrib3fv(2, colors + 3 * i);
550*8975f5c5SAndroid Build Coastguard Worker 
551*8975f5c5SAndroid Build Coastguard Worker         glDrawElements(GL_LINE_STRIP, ArraySize(lineloopAsStripIndices), GL_UNSIGNED_SHORT,
552*8975f5c5SAndroid Build Coastguard Worker                        lineloopAsStripIndices);
553*8975f5c5SAndroid Build Coastguard Worker     }
554*8975f5c5SAndroid Build Coastguard Worker 
555*8975f5c5SAndroid Build Coastguard Worker     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
556*8975f5c5SAndroid Build Coastguard Worker                  expectedPixels.data());
557*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
558*8975f5c5SAndroid Build Coastguard Worker 
559*8975f5c5SAndroid Build Coastguard Worker     // Draw in instanced way:
560*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
561*8975f5c5SAndroid Build Coastguard Worker 
562*8975f5c5SAndroid Build Coastguard Worker     GLBuffer vertexBuffer[3];
563*8975f5c5SAndroid Build Coastguard Worker     GLBuffer indexBuffer;
564*8975f5c5SAndroid Build Coastguard Worker 
565*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
566*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(lineloopAsStripIndices), lineloopAsStripIndices,
567*8975f5c5SAndroid Build Coastguard Worker                  GL_STATIC_DRAW);
568*8975f5c5SAndroid Build Coastguard Worker 
569*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[0]);
570*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
571*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(0);
572*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribDivisorANGLE(0, 0);
573*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
574*8975f5c5SAndroid Build Coastguard Worker 
575*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[1]);
576*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(transform), transform, GL_STATIC_DRAW);
577*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(1);
578*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribDivisorANGLE(1, 1);
579*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
580*8975f5c5SAndroid Build Coastguard Worker 
581*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[2]);
582*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
583*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(2);
584*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribDivisorANGLE(2, 1);
585*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);
586*8975f5c5SAndroid Build Coastguard Worker 
587*8975f5c5SAndroid Build Coastguard Worker     glDrawArraysInstancedANGLE(GL_LINE_LOOP, 0, ArraySize(vertices) / 2, instances);
588*8975f5c5SAndroid Build Coastguard Worker 
589*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLColor> actualPixels(getWindowWidth() * getWindowHeight());
590*8975f5c5SAndroid Build Coastguard Worker     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
591*8975f5c5SAndroid Build Coastguard Worker                  actualPixels.data());
592*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(expectedPixels, actualPixels);
593*8975f5c5SAndroid Build Coastguard Worker 
594*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
595*8975f5c5SAndroid Build Coastguard Worker     glDrawElementsInstancedANGLE(GL_LINE_LOOP, ArraySize(lineloopAsStripIndices) - 1,
596*8975f5c5SAndroid Build Coastguard Worker                                  GL_UNSIGNED_SHORT, 0, instances);
597*8975f5c5SAndroid Build Coastguard Worker 
598*8975f5c5SAndroid Build Coastguard Worker     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
599*8975f5c5SAndroid Build Coastguard Worker                  actualPixels.data());
600*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(expectedPixels, actualPixels);
601*8975f5c5SAndroid Build Coastguard Worker }
602*8975f5c5SAndroid Build Coastguard Worker 
603*8975f5c5SAndroid Build Coastguard Worker class InstancingTestES3 : public InstancingTest
604*8975f5c5SAndroid Build Coastguard Worker {
605*8975f5c5SAndroid Build Coastguard Worker   public:
InstancingTestES3()606*8975f5c5SAndroid Build Coastguard Worker     InstancingTestES3() {}
607*8975f5c5SAndroid Build Coastguard Worker };
608*8975f5c5SAndroid Build Coastguard Worker 
609*8975f5c5SAndroid Build Coastguard Worker class InstancingTestES31 : public InstancingTest
610*8975f5c5SAndroid Build Coastguard Worker {
611*8975f5c5SAndroid Build Coastguard Worker   public:
InstancingTestES31()612*8975f5c5SAndroid Build Coastguard Worker     InstancingTestES31() {}
613*8975f5c5SAndroid Build Coastguard Worker };
614*8975f5c5SAndroid Build Coastguard Worker 
615*8975f5c5SAndroid Build Coastguard Worker // Verify that VertexAttribDivisor can update both binding divisor and attribBinding.
TEST_P(InstancingTestES31,UpdateAttribBindingByVertexAttribDivisor)616*8975f5c5SAndroid Build Coastguard Worker TEST_P(InstancingTestES31, UpdateAttribBindingByVertexAttribDivisor)
617*8975f5c5SAndroid Build Coastguard Worker {
618*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_instanced_arrays"));
619*8975f5c5SAndroid Build Coastguard Worker 
620*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(mProgram[0]);
621*8975f5c5SAndroid Build Coastguard Worker 
622*8975f5c5SAndroid Build Coastguard Worker     // Get the attribute locations
623*8975f5c5SAndroid Build Coastguard Worker     GLint positionLoc    = glGetAttribLocation(mProgram[0], "a_position");
624*8975f5c5SAndroid Build Coastguard Worker     GLint instancePosLoc = glGetAttribLocation(mProgram[0], "a_instance");
625*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(-1, positionLoc);
626*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(-1, instancePosLoc);
627*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
628*8975f5c5SAndroid Build Coastguard Worker 
629*8975f5c5SAndroid Build Coastguard Worker     GLuint vao;
630*8975f5c5SAndroid Build Coastguard Worker     glGenVertexArrays(1, &vao);
631*8975f5c5SAndroid Build Coastguard Worker     glBindVertexArray(vao);
632*8975f5c5SAndroid Build Coastguard Worker 
633*8975f5c5SAndroid Build Coastguard Worker     GLBuffer quadBuffer;
634*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, quadBuffer);
635*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(kQuadVertices), kQuadVertices, GL_STATIC_DRAW);
636*8975f5c5SAndroid Build Coastguard Worker 
637*8975f5c5SAndroid Build Coastguard Worker     const unsigned numInstance = 4;
638*8975f5c5SAndroid Build Coastguard Worker     const unsigned divisor     = 1;
639*8975f5c5SAndroid Build Coastguard Worker     const unsigned lastDrawn   = (numInstance - 1) / divisor;
640*8975f5c5SAndroid Build Coastguard Worker 
641*8975f5c5SAndroid Build Coastguard Worker     // Ensure the numInstance and divisor parameters are valid.
642*8975f5c5SAndroid Build Coastguard Worker     ASSERT_TRUE(lastDrawn < kMaxDrawn);
643*8975f5c5SAndroid Build Coastguard Worker 
644*8975f5c5SAndroid Build Coastguard Worker     // Set the formats by VertexAttribFormat
645*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribFormat(positionLoc, 2, GL_FLOAT, GL_FALSE, 0);
646*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribFormat(instancePosLoc, 1, GL_FLOAT, GL_FALSE, 0);
647*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(positionLoc);
648*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(instancePosLoc);
649*8975f5c5SAndroid Build Coastguard Worker 
650*8975f5c5SAndroid Build Coastguard Worker     const GLint positionBinding = instancePosLoc;
651*8975f5c5SAndroid Build Coastguard Worker     const GLint instanceBinding = positionLoc;
652*8975f5c5SAndroid Build Coastguard Worker 
653*8975f5c5SAndroid Build Coastguard Worker     // Load the vertex position into the binding indexed positionBinding (== instancePosLoc)
654*8975f5c5SAndroid Build Coastguard Worker     // Load the instance position into the binding indexed instanceBinding (== positionLoc)
655*8975f5c5SAndroid Build Coastguard Worker     glBindVertexBuffer(positionBinding, quadBuffer, 0, 2 * sizeof(kQuadVertices[0]));
656*8975f5c5SAndroid Build Coastguard Worker     glBindVertexBuffer(instanceBinding, mInstanceBuffer, 0, sizeof(mInstanceData[0]));
657*8975f5c5SAndroid Build Coastguard Worker 
658*8975f5c5SAndroid Build Coastguard Worker     // The attribute indexed positionLoc is using the binding indexed positionBinding
659*8975f5c5SAndroid Build Coastguard Worker     // The attribute indexed instancePosLoc is using the binding indexed instanceBinding
660*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribBinding(positionLoc, positionBinding);
661*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribBinding(instancePosLoc, instanceBinding);
662*8975f5c5SAndroid Build Coastguard Worker 
663*8975f5c5SAndroid Build Coastguard Worker     // Enable instancing on the binding indexed instanceBinding
664*8975f5c5SAndroid Build Coastguard Worker     glVertexBindingDivisor(instanceBinding, divisor);
665*8975f5c5SAndroid Build Coastguard Worker 
666*8975f5c5SAndroid Build Coastguard Worker     // Do the first instanced draw
667*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
668*8975f5c5SAndroid Build Coastguard Worker     glDrawElementsInstanced(GL_TRIANGLES, ArraySize(kQuadIndices), GL_UNSIGNED_SHORT, kQuadIndices,
669*8975f5c5SAndroid Build Coastguard Worker                             numInstance);
670*8975f5c5SAndroid Build Coastguard Worker     checkDrawing(lastDrawn);
671*8975f5c5SAndroid Build Coastguard Worker 
672*8975f5c5SAndroid Build Coastguard Worker     // Disable instancing.
673*8975f5c5SAndroid Build Coastguard Worker     glVertexBindingDivisor(instanceBinding, 0);
674*8975f5c5SAndroid Build Coastguard Worker 
675*8975f5c5SAndroid Build Coastguard Worker     // Load the vertex position into the binding indexed positionLoc.
676*8975f5c5SAndroid Build Coastguard Worker     // Load the instance position into the binding indexed instancePosLoc.
677*8975f5c5SAndroid Build Coastguard Worker     glBindVertexBuffer(positionLoc, quadBuffer, 0, 2 * sizeof(kQuadVertices[0]));
678*8975f5c5SAndroid Build Coastguard Worker     glBindVertexBuffer(instancePosLoc, mInstanceBuffer, 0, sizeof(mInstanceData[0]));
679*8975f5c5SAndroid Build Coastguard Worker 
680*8975f5c5SAndroid Build Coastguard Worker     // The attribute indexed positionLoc is using the binding indexed positionLoc.
681*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribBinding(positionLoc, positionLoc);
682*8975f5c5SAndroid Build Coastguard Worker 
683*8975f5c5SAndroid Build Coastguard Worker     // Call VertexAttribDivisor to both enable instancing on instancePosLoc and set the attribute
684*8975f5c5SAndroid Build Coastguard Worker     // indexed instancePosLoc using the binding indexed instancePosLoc.
685*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribDivisor(instancePosLoc, divisor);
686*8975f5c5SAndroid Build Coastguard Worker 
687*8975f5c5SAndroid Build Coastguard Worker     // Do the second instanced draw
688*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
689*8975f5c5SAndroid Build Coastguard Worker     glDrawElementsInstanced(GL_TRIANGLES, ArraySize(kQuadIndices), GL_UNSIGNED_SHORT, kQuadIndices,
690*8975f5c5SAndroid Build Coastguard Worker                             numInstance);
691*8975f5c5SAndroid Build Coastguard Worker     checkDrawing(lastDrawn);
692*8975f5c5SAndroid Build Coastguard Worker 
693*8975f5c5SAndroid Build Coastguard Worker     glDeleteVertexArrays(1, &vao);
694*8975f5c5SAndroid Build Coastguard Worker }
695*8975f5c5SAndroid Build Coastguard Worker 
696*8975f5c5SAndroid Build Coastguard Worker // Verify that a large divisor that also changes doesn't cause issues and renders correctly.
TEST_P(InstancingTestES3,LargeDivisor)697*8975f5c5SAndroid Build Coastguard Worker TEST_P(InstancingTestES3, LargeDivisor)
698*8975f5c5SAndroid Build Coastguard Worker {
699*8975f5c5SAndroid Build Coastguard Worker     constexpr char kVS[] = R"(#version 300 es
700*8975f5c5SAndroid Build Coastguard Worker layout(location = 0) in vec4 a_position;
701*8975f5c5SAndroid Build Coastguard Worker layout(location = 1) in vec4 a_color;
702*8975f5c5SAndroid Build Coastguard Worker out vec4 v_color;
703*8975f5c5SAndroid Build Coastguard Worker void main()
704*8975f5c5SAndroid Build Coastguard Worker {
705*8975f5c5SAndroid Build Coastguard Worker     gl_Position = a_position;
706*8975f5c5SAndroid Build Coastguard Worker     gl_PointSize = 4.0f;
707*8975f5c5SAndroid Build Coastguard Worker     v_color = a_color;
708*8975f5c5SAndroid Build Coastguard Worker })";
709*8975f5c5SAndroid Build Coastguard Worker 
710*8975f5c5SAndroid Build Coastguard Worker     constexpr char kFS[] = R"(#version 300 es
711*8975f5c5SAndroid Build Coastguard Worker precision highp float;
712*8975f5c5SAndroid Build Coastguard Worker in vec4 v_color;
713*8975f5c5SAndroid Build Coastguard Worker out vec4 my_FragColor;
714*8975f5c5SAndroid Build Coastguard Worker void main()
715*8975f5c5SAndroid Build Coastguard Worker {
716*8975f5c5SAndroid Build Coastguard Worker     my_FragColor = v_color;
717*8975f5c5SAndroid Build Coastguard Worker })";
718*8975f5c5SAndroid Build Coastguard Worker 
719*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(program, kVS, kFS);
720*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
721*8975f5c5SAndroid Build Coastguard Worker 
722*8975f5c5SAndroid Build Coastguard Worker     glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
723*8975f5c5SAndroid Build Coastguard Worker 
724*8975f5c5SAndroid Build Coastguard Worker     GLBuffer buf;
725*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, buf);
726*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLfloat> vertices;
727*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0u; i < 4u; ++i)
728*8975f5c5SAndroid Build Coastguard Worker     {
729*8975f5c5SAndroid Build Coastguard Worker         vertices.push_back(0.0f + i * 0.25f);
730*8975f5c5SAndroid Build Coastguard Worker         vertices.push_back(0.0f);
731*8975f5c5SAndroid Build Coastguard Worker         vertices.push_back(0.0f);
732*8975f5c5SAndroid Build Coastguard Worker         vertices.push_back(1.0f);
733*8975f5c5SAndroid Build Coastguard Worker     }
734*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, vertices.size() * 4u, vertices.data(), GL_DYNAMIC_DRAW);
735*8975f5c5SAndroid Build Coastguard Worker 
736*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(0);
737*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, nullptr);
738*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
739*8975f5c5SAndroid Build Coastguard Worker 
740*8975f5c5SAndroid Build Coastguard Worker     GLBuffer colorBuf;
741*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, colorBuf);
742*8975f5c5SAndroid Build Coastguard Worker 
743*8975f5c5SAndroid Build Coastguard Worker     std::array<GLColor, 4> ubyteColors = {GLColor::red, GLColor::green};
744*8975f5c5SAndroid Build Coastguard Worker     std::vector<float> floatColors;
745*8975f5c5SAndroid Build Coastguard Worker     for (const GLColor &color : ubyteColors)
746*8975f5c5SAndroid Build Coastguard Worker     {
747*8975f5c5SAndroid Build Coastguard Worker         floatColors.push_back(color.R / 255.0f);
748*8975f5c5SAndroid Build Coastguard Worker         floatColors.push_back(color.G / 255.0f);
749*8975f5c5SAndroid Build Coastguard Worker         floatColors.push_back(color.B / 255.0f);
750*8975f5c5SAndroid Build Coastguard Worker         floatColors.push_back(color.A / 255.0f);
751*8975f5c5SAndroid Build Coastguard Worker     }
752*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, floatColors.size() * 4u, floatColors.data(), GL_DYNAMIC_DRAW);
753*8975f5c5SAndroid Build Coastguard Worker 
754*8975f5c5SAndroid Build Coastguard Worker     const GLuint kColorDivisor = 65536u * 2u;
755*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(1);
756*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(1, 4, GL_FLOAT, false, 0, nullptr);
757*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribDivisor(1, kColorDivisor);
758*8975f5c5SAndroid Build Coastguard Worker 
759*8975f5c5SAndroid Build Coastguard Worker     std::array<GLuint, 1u> indices       = {0u};
760*8975f5c5SAndroid Build Coastguard Worker     std::array<GLuint, 3u> divisorsToTry = {256u, 65536u, 65536u * 2u};
761*8975f5c5SAndroid Build Coastguard Worker 
762*8975f5c5SAndroid Build Coastguard Worker     for (GLuint divisorToTry : divisorsToTry)
763*8975f5c5SAndroid Build Coastguard Worker     {
764*8975f5c5SAndroid Build Coastguard Worker         glClear(GL_COLOR_BUFFER_BIT);
765*8975f5c5SAndroid Build Coastguard Worker         glVertexAttribDivisor(0, divisorToTry);
766*8975f5c5SAndroid Build Coastguard Worker 
767*8975f5c5SAndroid Build Coastguard Worker         GLuint instanceCount        = divisorToTry + 1u;
768*8975f5c5SAndroid Build Coastguard Worker         unsigned int pointsRendered = (instanceCount - 1u) / divisorToTry + 1u;
769*8975f5c5SAndroid Build Coastguard Worker 
770*8975f5c5SAndroid Build Coastguard Worker         glDrawElementsInstanced(GL_POINTS, indices.size(), GL_UNSIGNED_INT, indices.data(),
771*8975f5c5SAndroid Build Coastguard Worker                                 instanceCount);
772*8975f5c5SAndroid Build Coastguard Worker         ASSERT_GL_NO_ERROR();
773*8975f5c5SAndroid Build Coastguard Worker 
774*8975f5c5SAndroid Build Coastguard Worker         // Check that the intended number of points has been rendered.
775*8975f5c5SAndroid Build Coastguard Worker         for (unsigned int pointIndex = 0u; pointIndex < pointsRendered + 1u; ++pointIndex)
776*8975f5c5SAndroid Build Coastguard Worker         {
777*8975f5c5SAndroid Build Coastguard Worker             GLint pointx = static_cast<GLint>((pointIndex * 0.125f + 0.5f) * getWindowWidth());
778*8975f5c5SAndroid Build Coastguard Worker             GLint pointy = static_cast<GLint>(0.5f * getWindowHeight());
779*8975f5c5SAndroid Build Coastguard Worker 
780*8975f5c5SAndroid Build Coastguard Worker             if (pointIndex < pointsRendered)
781*8975f5c5SAndroid Build Coastguard Worker             {
782*8975f5c5SAndroid Build Coastguard Worker                 GLuint pointColorIndex = (pointIndex * divisorToTry) / kColorDivisor;
783*8975f5c5SAndroid Build Coastguard Worker                 EXPECT_PIXEL_COLOR_EQ(pointx, pointy, ubyteColors[pointColorIndex]);
784*8975f5c5SAndroid Build Coastguard Worker             }
785*8975f5c5SAndroid Build Coastguard Worker             else
786*8975f5c5SAndroid Build Coastguard Worker             {
787*8975f5c5SAndroid Build Coastguard Worker                 // Clear color.
788*8975f5c5SAndroid Build Coastguard Worker                 EXPECT_PIXEL_COLOR_EQ(pointx, pointy, GLColor::blue);
789*8975f5c5SAndroid Build Coastguard Worker             }
790*8975f5c5SAndroid Build Coastguard Worker         }
791*8975f5c5SAndroid Build Coastguard Worker     }
792*8975f5c5SAndroid Build Coastguard Worker }
793*8975f5c5SAndroid Build Coastguard Worker 
794*8975f5c5SAndroid Build Coastguard Worker // This is a regression test. If VertexAttribDivisor was returned as a signed integer, it would be
795*8975f5c5SAndroid Build Coastguard Worker // incorrectly clamped down to the maximum signed integer.
TEST_P(InstancingTestES3,LargestDivisor)796*8975f5c5SAndroid Build Coastguard Worker TEST_P(InstancingTestES3, LargestDivisor)
797*8975f5c5SAndroid Build Coastguard Worker {
798*8975f5c5SAndroid Build Coastguard Worker     constexpr GLuint kLargeDivisor = std::numeric_limits<GLuint>::max();
799*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribDivisor(0, kLargeDivisor);
800*8975f5c5SAndroid Build Coastguard Worker 
801*8975f5c5SAndroid Build Coastguard Worker     GLuint divisor = 0;
802*8975f5c5SAndroid Build Coastguard Worker     glGetVertexAttribIuiv(0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, &divisor);
803*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(kLargeDivisor, divisor)
804*8975f5c5SAndroid Build Coastguard Worker         << "Vertex attrib divisor read was not the same that was passed in.";
805*8975f5c5SAndroid Build Coastguard Worker }
806*8975f5c5SAndroid Build Coastguard Worker 
807*8975f5c5SAndroid Build Coastguard Worker // Regression test for D3D11 streaming of GL_DYNAMIC_DRAW buffers not taking into account instanced
808*8975f5c5SAndroid Build Coastguard Worker // attributes for buffer size calculations. http://crbug.com/1425606
TEST_P(InstancingTestES3,D3D11StreamingInstancedData)809*8975f5c5SAndroid Build Coastguard Worker TEST_P(InstancingTestES3, D3D11StreamingInstancedData)
810*8975f5c5SAndroid Build Coastguard Worker {
811*8975f5c5SAndroid Build Coastguard Worker     constexpr char kVS[] = R"(#version 300 es
812*8975f5c5SAndroid Build Coastguard Worker in float scale;
813*8975f5c5SAndroid Build Coastguard Worker void main()
814*8975f5c5SAndroid Build Coastguard Worker {
815*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(vec2(gl_VertexID % 2, gl_VertexID % 3) * scale, 0, 1);
816*8975f5c5SAndroid Build Coastguard Worker })";
817*8975f5c5SAndroid Build Coastguard Worker 
818*8975f5c5SAndroid Build Coastguard Worker     constexpr char kFS[] = R"(#version 300 es
819*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
820*8975f5c5SAndroid Build Coastguard Worker out vec4 color;
821*8975f5c5SAndroid Build Coastguard Worker void main()
822*8975f5c5SAndroid Build Coastguard Worker {
823*8975f5c5SAndroid Build Coastguard Worker     color = vec4(1, 0, 0, 1);
824*8975f5c5SAndroid Build Coastguard Worker })";
825*8975f5c5SAndroid Build Coastguard Worker 
826*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(program, kVS, kFS);
827*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
828*8975f5c5SAndroid Build Coastguard Worker 
829*8975f5c5SAndroid Build Coastguard Worker     GLBuffer buffer;
830*8975f5c5SAndroid Build Coastguard Worker     float data = 0.5f;
831*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, buffer);
832*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(data), &data, GL_DYNAMIC_DRAW);
833*8975f5c5SAndroid Build Coastguard Worker 
834*8975f5c5SAndroid Build Coastguard Worker     GLint loc = glGetAttribLocation(program, "scale");
835*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(loc);
836*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(loc, 1, GL_FLOAT, false, 0, 0);
837*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribDivisor(loc, 1);
838*8975f5c5SAndroid Build Coastguard Worker 
839*8975f5c5SAndroid Build Coastguard Worker     // Both of these should succeed
840*8975f5c5SAndroid Build Coastguard Worker     glDrawArraysInstanced(GL_TRIANGLES, 0, 3, 1);
841*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
842*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_TRIANGLES, 0, 3);
843*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
844*8975f5c5SAndroid Build Coastguard Worker }
845*8975f5c5SAndroid Build Coastguard Worker 
846*8975f5c5SAndroid Build Coastguard Worker // Regression test for D3D11 streaming of GL_DYNAMIC_DRAW buffers not taking into account instanced
847*8975f5c5SAndroid Build Coastguard Worker // attributes for buffer size calculations. http://crbug.com/1425606
TEST_P(InstancingTestES3,D3D11StreamingInstancedData2)848*8975f5c5SAndroid Build Coastguard Worker TEST_P(InstancingTestES3, D3D11StreamingInstancedData2)
849*8975f5c5SAndroid Build Coastguard Worker {
850*8975f5c5SAndroid Build Coastguard Worker     constexpr char kVS[] = R"(#version 300 es
851*8975f5c5SAndroid Build Coastguard Worker in float scale;
852*8975f5c5SAndroid Build Coastguard Worker void main()
853*8975f5c5SAndroid Build Coastguard Worker {
854*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(vec2(gl_VertexID % 2, gl_VertexID % 3) * scale, 0, 1);
855*8975f5c5SAndroid Build Coastguard Worker     gl_PointSize = 1.0;
856*8975f5c5SAndroid Build Coastguard Worker })";
857*8975f5c5SAndroid Build Coastguard Worker 
858*8975f5c5SAndroid Build Coastguard Worker     constexpr char kFS[] = R"(#version 300 es
859*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
860*8975f5c5SAndroid Build Coastguard Worker out vec4 color;
861*8975f5c5SAndroid Build Coastguard Worker void main()
862*8975f5c5SAndroid Build Coastguard Worker {
863*8975f5c5SAndroid Build Coastguard Worker     color = vec4(1, 0, 0, 1);
864*8975f5c5SAndroid Build Coastguard Worker })";
865*8975f5c5SAndroid Build Coastguard Worker 
866*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(program, kVS, kFS);
867*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
868*8975f5c5SAndroid Build Coastguard Worker 
869*8975f5c5SAndroid Build Coastguard Worker     GLBuffer buffer;
870*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, buffer);
871*8975f5c5SAndroid Build Coastguard Worker 
872*8975f5c5SAndroid Build Coastguard Worker     GLint loc = glGetAttribLocation(program, "scale");
873*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(loc);
874*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(loc, 1, GL_FLOAT, false, 0, 0);
875*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribDivisor(loc, 10001);
876*8975f5c5SAndroid Build Coastguard Worker 
877*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0; i < 100; i++)
878*8975f5c5SAndroid Build Coastguard Worker     {
879*8975f5c5SAndroid Build Coastguard Worker         float data = 0.5f;
880*8975f5c5SAndroid Build Coastguard Worker         glBufferData(GL_ARRAY_BUFFER, sizeof(data), &data, GL_DYNAMIC_DRAW);
881*8975f5c5SAndroid Build Coastguard Worker 
882*8975f5c5SAndroid Build Coastguard Worker         glDrawArrays(GL_POINTS, 0, 10000);
883*8975f5c5SAndroid Build Coastguard Worker         EXPECT_GL_NO_ERROR();
884*8975f5c5SAndroid Build Coastguard Worker     }
885*8975f5c5SAndroid Build Coastguard Worker }
886*8975f5c5SAndroid Build Coastguard Worker 
887*8975f5c5SAndroid Build Coastguard Worker GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(InstancingTestES3);
888*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES3(InstancingTestES3);
889*8975f5c5SAndroid Build Coastguard Worker 
890*8975f5c5SAndroid Build Coastguard Worker GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(InstancingTestES31);
891*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES31(InstancingTestES31);
892*8975f5c5SAndroid Build Coastguard Worker 
893*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES2(InstancingTest);
894