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