xref: /aosp_15_r20/external/angle/src/tests/gl_tests/DrawBaseVertexBaseInstanceTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2019 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // DrawBaseVertexBaseInstanceTest: Tests of GL_ANGLE_base_vertex_base_instance
8 // DrawBaseInstanceTest: Tests of GL_EXT_base_instance
9 
10 #include "gpu_info_util/SystemInfo.h"
11 #include "test_utils/ANGLETest.h"
12 #include "test_utils/gl_raii.h"
13 
14 #include <numeric>
15 
16 using namespace angle;
17 
18 namespace
19 {
20 
21 // Create a kWidth * kHeight canvas equally split into kCountX * kCountY tiles
22 // each containing a quad partially covering each tile
23 constexpr uint32_t kWidth                  = 256;
24 constexpr uint32_t kHeight                 = 256;
25 constexpr uint32_t kCountX                 = 8;
26 constexpr uint32_t kCountY                 = 8;
27 constexpr std::array<GLfloat, 2> kTileSize = {
28     1.f / static_cast<GLfloat>(kCountX),
29     1.f / static_cast<GLfloat>(kCountY),
30 };
31 constexpr std::array<uint32_t, 2> kTilePixelSize  = {kWidth / kCountX, kHeight / kCountY};
32 constexpr std::array<GLfloat, 2> kQuadRadius      = {0.25f * kTileSize[0], 0.25f * kTileSize[1]};
33 constexpr std::array<uint32_t, 2> kPixelCheckSize = {
34     static_cast<uint32_t>(kQuadRadius[0] * kWidth),
35     static_cast<uint32_t>(kQuadRadius[1] * kHeight)};
36 
getTileCenter(uint32_t x,uint32_t y)37 constexpr std::array<GLfloat, 2> getTileCenter(uint32_t x, uint32_t y)
38 {
39     return {
40         kTileSize[0] * (0.5f + static_cast<GLfloat>(x)),
41         kTileSize[1] * (0.5f + static_cast<GLfloat>(y)),
42     };
43 }
getQuadVertices(uint32_t x,uint32_t y)44 constexpr std::array<std::array<GLfloat, 3>, 4> getQuadVertices(uint32_t x, uint32_t y)
45 {
46     const auto center = getTileCenter(x, y);
47     return {
48         std::array<GLfloat, 3>{center[0] - kQuadRadius[0], center[1] - kQuadRadius[1], 0.0f},
49         std::array<GLfloat, 3>{center[0] + kQuadRadius[0], center[1] - kQuadRadius[1], 0.0f},
50         std::array<GLfloat, 3>{center[0] + kQuadRadius[0], center[1] + kQuadRadius[1], 0.0f},
51         std::array<GLfloat, 3>{center[0] - kQuadRadius[0], center[1] + kQuadRadius[1], 0.0f},
52     };
53 }
54 
55 enum class BaseVertexOption
56 {
57     NoBaseVertex,
58     UseBaseVertex
59 };
60 
61 enum class BaseInstanceOption
62 {
63     NoBaseInstance,
64     UseBaseInstance
65 };
66 
67 enum class BufferDataUsageOption
68 {
69     StaticDraw,
70     DynamicDraw
71 };
72 
73 using DrawBaseVertexBaseInstanceTestParams = std::
74     tuple<angle::PlatformParameters, BaseVertexOption, BaseInstanceOption, BufferDataUsageOption>;
75 
76 struct PrintToStringParamName
77 {
operator ()__anon3913e2b20111::PrintToStringParamName78     std::string operator()(
79         const ::testing::TestParamInfo<DrawBaseVertexBaseInstanceTestParams> &info) const
80     {
81         ::std::stringstream ss;
82         ss << std::get<0>(info.param) << "_"
83            << (std::get<3>(info.param) == BufferDataUsageOption::StaticDraw ? "_StaticDraw"
84                                                                             : "_DynamicDraw")
85            << (std::get<2>(info.param) == BaseInstanceOption::UseBaseInstance ? "_UseBaseInstance"
86                                                                               : "")
87            << (std::get<1>(info.param) == BaseVertexOption::UseBaseVertex ? "_UseBaseVertex" : "");
88         return ss.str();
89     }
90 };
91 
92 // These tests check correctness of the ANGLE_base_vertex_base_instance extension.
93 // An array of quads is drawn across the screen.
94 // gl_VertexID, gl_InstanceID, gl_BaseVertex, and gl_BaseInstance
95 // are checked by using them to select the color of the draw.
96 class DrawBaseVertexBaseInstanceTest
97     : public ANGLETestBase,
98       public ::testing::TestWithParam<DrawBaseVertexBaseInstanceTestParams>
99 {
100   protected:
DrawBaseVertexBaseInstanceTest()101     DrawBaseVertexBaseInstanceTest() : ANGLETestBase(std::get<0>(GetParam()))
102     {
103         setWindowWidth(kWidth);
104         setWindowHeight(kHeight);
105         setConfigRedBits(8);
106         setConfigGreenBits(8);
107         setConfigBlueBits(8);
108         setConfigAlphaBits(8);
109 
110         // Rects in the same column are within a vertex array, testing gl_VertexID, gl_BaseVertex
111         // Rects in the same row are drawn by instancing, testing gl_InstanceID, gl_BaseInstance
112 
113         mIndices = {0, 1, 2, 0, 2, 3};
114 
115         for (uint32_t y = 0; y < kCountY; ++y)
116         {
117             // v3 ---- v2
118             // |       |
119             // |       |
120             // v0 ---- v1
121 
122             const auto vs = getQuadVertices(0, y);
123 
124             for (const auto &v : vs)
125             {
126                 mVertices.insert(mVertices.end(), v.begin(), v.end());
127             }
128 
129             for (GLushort i : mIndices)
130             {
131                 mNonIndexedVertices.insert(mNonIndexedVertices.end(), vs[i].begin(), vs[i].end());
132             }
133         }
134 
135         mRegularIndices.resize(kCountY * mIndices.size());
136         for (uint32_t i = 0; i < kCountY; i++)
137         {
138             uint32_t oi = 6 * i;
139             uint32_t ov = 4 * i;
140             for (uint32_t j = 0; j < 6; j++)
141             {
142                 mRegularIndices[oi + j] = mIndices[j] + ov;
143             }
144         }
145 
146         std::iota(mInstancedArrayId.begin(), mInstancedArrayId.end(), 0.0f);
147         std::reverse_copy(mInstancedArrayId.begin(), mInstancedArrayId.end(),
148                           mInstancedArrayColorId.begin());
149     }
150 
SetUp()151     void SetUp() override { ANGLETestBase::ANGLETestSetUp(); }
152 
useBaseVertexBuiltin() const153     bool useBaseVertexBuiltin() const
154     {
155         return std::get<1>(GetParam()) == BaseVertexOption::UseBaseVertex;
156     }
157 
useBaseInstanceBuiltin() const158     bool useBaseInstanceBuiltin() const
159     {
160         return std::get<2>(GetParam()) == BaseInstanceOption::UseBaseInstance;
161     }
162 
getBufferDataUsage() const163     GLenum getBufferDataUsage() const
164     {
165         return std::get<3>(GetParam()) == BufferDataUsageOption::StaticDraw ? GL_STATIC_DRAW
166                                                                             : GL_DYNAMIC_DRAW;
167     }
168 
vertexShaderSource300(bool isDrawArrays,bool isMultiDraw,bool divisorTest)169     std::string vertexShaderSource300(bool isDrawArrays, bool isMultiDraw, bool divisorTest)
170     {
171         // Each color channel is to test the value of
172         // R: gl_InstanceID and gl_BaseInstance
173         // G: gl_VertexID and gl_BaseVertex
174         // B: gl_BaseVertex
175 
176         std::stringstream shader;
177         shader << ("#version 300 es\n")
178                << (isMultiDraw ? "#extension GL_ANGLE_multi_draw : require\n" : "")
179                << ("#extension GL_ANGLE_base_vertex_base_instance_shader_builtin : require\n")
180                << "#define kCountX " << kCountX << "\n"
181                << "#define kCountY " << kCountY << "\n"
182                << R"(
183 in vec2 vPosition;
184 )" << (useBaseInstanceBuiltin() ? "" : "in float vInstanceID;\n")
185                << (!divisorTest ? "" : "in float vInstanceColorID;\n") << R"(
186 out vec4 color;
187 void main()
188 {
189     const float xStep = 1.0 / float(kCountX);
190     const float yStep = 1.0 / float(kCountY);
191     float x_id = )"
192                << (useBaseInstanceBuiltin() ? " float(gl_InstanceID + gl_BaseInstance);"
193                                             : "vInstanceID;")
194                << "float x_color = "
195                << (divisorTest ? "xStep * (vInstanceColorID + 1.0f);" : " 1.0 - xStep * x_id;")
196                << R"(
197     float y_id = float(gl_VertexID / )"
198                << (isDrawArrays ? "6" : "4") << R"();
199 
200     color = vec4(
201         x_color,
202         1.0 - yStep * y_id,
203         )" << (useBaseVertexBuiltin() ? "1.0 - yStep * float(gl_BaseVertex) / 4.0" : "1.0")
204                << R"(,
205         1);
206 
207     mat3 transform = mat3(1.0);
208     transform[2][0] = x_id * xStep;
209 
210     gl_Position = vec4(transform * vec3(vPosition, 1.0) * 2.0 - 1.0, 1);
211 })";
212 
213         return shader.str();
214     }
215 
fragmentShaderSource300()216     std::string fragmentShaderSource300()
217     {
218         return
219             R"(#version 300 es
220 precision mediump float;
221 in vec4 color;
222 out vec4 o_color;
223 void main()
224 {
225     o_color = color;
226 })";
227     }
228 
setupProgram(GLProgram & program,bool isDrawArrays=true,bool isMultiDraw=false,bool isDivisorTest=false)229     void setupProgram(GLProgram &program,
230                       bool isDrawArrays  = true,
231                       bool isMultiDraw   = false,
232                       bool isDivisorTest = false)
233     {
234         program.makeRaster(vertexShaderSource300(isDrawArrays, isMultiDraw, isDivisorTest).c_str(),
235                            fragmentShaderSource300().c_str());
236         EXPECT_GL_NO_ERROR();
237         ASSERT_TRUE(program.valid());
238         glUseProgram(program);
239         mPositionLoc = glGetAttribLocation(program, "vPosition");
240         if (!useBaseInstanceBuiltin())
241         {
242             mInstanceIDLoc      = glGetAttribLocation(program, "vInstanceID");
243             mInstanceColorIDLoc = glGetAttribLocation(program, "vInstanceColorID");
244         }
245     }
246 
setupNonIndexedBuffers(GLBuffer & vertexBuffer)247     void setupNonIndexedBuffers(GLBuffer &vertexBuffer)
248     {
249         glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
250         glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mNonIndexedVertices.size(),
251                      mNonIndexedVertices.data(), getBufferDataUsage());
252 
253         ASSERT_GL_NO_ERROR();
254     }
255 
setupIndexedBuffers(GLBuffer & vertexBuffer,GLBuffer & indexBuffer)256     void setupIndexedBuffers(GLBuffer &vertexBuffer, GLBuffer &indexBuffer)
257     {
258         glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
259         glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mVertices.size(), mVertices.data(),
260                      getBufferDataUsage());
261 
262         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
263         glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * mIndices.size(), mIndices.data(),
264                      getBufferDataUsage());
265 
266         ASSERT_GL_NO_ERROR();
267     }
268 
setupInstanceIDBuffer(GLBuffer & instanceIDBuffer)269     void setupInstanceIDBuffer(GLBuffer &instanceIDBuffer)
270     {
271         glBindBuffer(GL_ARRAY_BUFFER, instanceIDBuffer);
272         glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mInstancedArrayId.size(),
273                      mInstancedArrayId.data(), getBufferDataUsage());
274 
275         ASSERT_GL_NO_ERROR();
276     }
277 
setupInstanceColorIDBuffer(GLBuffer & instanceIDBuffer)278     void setupInstanceColorIDBuffer(GLBuffer &instanceIDBuffer)
279     {
280         glBindBuffer(GL_ARRAY_BUFFER, instanceIDBuffer);
281         glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mInstancedArrayColorId.size(),
282                      mInstancedArrayColorId.data(), getBufferDataUsage());
283 
284         ASSERT_GL_NO_ERROR();
285     }
286 
setupRegularIndexedBuffer(GLBuffer & indexBuffer)287     void setupRegularIndexedBuffer(GLBuffer &indexBuffer)
288     {
289         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
290         glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * mRegularIndices.size(),
291                      mRegularIndices.data(), getBufferDataUsage());
292 
293         ASSERT_GL_NO_ERROR();
294     }
295 
setupPositionVertexAttribPointer()296     void setupPositionVertexAttribPointer()
297     {
298         glEnableVertexAttribArray(mPositionLoc);
299         glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
300     }
301 
setupInstanceIDVertexAttribPointer(GLuint instanceIDLoc)302     void setupInstanceIDVertexAttribPointer(GLuint instanceIDLoc)
303     {
304         glEnableVertexAttribArray(instanceIDLoc);
305         glVertexAttribPointer(instanceIDLoc, 1, GL_FLOAT, GL_FALSE, 0, 0);
306         glVertexAttribDivisor(instanceIDLoc, 1);
307     }
308 
doDrawArraysInstancedBaseInstance()309     void doDrawArraysInstancedBaseInstance()
310     {
311         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
312 
313         const uint32_t countPerDraw = kCountY * 6;
314 
315         for (uint32_t i = 0; i < kCountX; i += 2)
316         {
317             glDrawArraysInstancedBaseInstanceANGLE(GL_TRIANGLES, 0, countPerDraw, 2, i);
318         }
319     }
320 
doMultiDrawArraysInstancedBaseInstance()321     void doMultiDrawArraysInstancedBaseInstance()
322     {
323         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
324 
325         const uint32_t countPerDraw = kCountY * 6;
326 
327         const GLsizei drawCount = kCountX / 2;
328         const std::vector<GLsizei> counts(drawCount, countPerDraw);
329         const std::vector<GLsizei> firsts(drawCount, 0);
330         const std::vector<GLsizei> instanceCounts(drawCount, 2);
331         std::vector<GLuint> baseInstances(drawCount);
332         for (size_t i = 0; i < drawCount; i++)
333         {
334             baseInstances[i] = i * 2;
335         }
336         glMultiDrawArraysInstancedBaseInstanceANGLE(GL_TRIANGLES, firsts.data(), counts.data(),
337                                                     instanceCounts.data(), baseInstances.data(),
338                                                     drawCount);
339     }
340 
doDrawElementsInstancedBaseVertexBaseInstance()341     void doDrawElementsInstancedBaseVertexBaseInstance()
342     {
343         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
344 
345         const uint32_t countPerDraw = 6;
346 
347         for (uint32_t v = 0; v < kCountY; v++)
348         {
349             for (uint32_t i = 0; i < kCountX; i += 2)
350             {
351                 glDrawElementsInstancedBaseVertexBaseInstanceANGLE(
352                     GL_TRIANGLES, countPerDraw, GL_UNSIGNED_SHORT,
353                     reinterpret_cast<GLvoid *>(static_cast<uintptr_t>(0)), 2, v * 4, i);
354             }
355         }
356     }
357 
358     // Call this after the *BaseVertexBaseInstance draw call to check if value of BaseVertex and
359     // BaseInstance are reset to zero
doDrawArraysBaseInstanceReset()360     void doDrawArraysBaseInstanceReset()
361     {
362         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
363         glDrawArraysInstanced(GL_TRIANGLES, 0, 6 * kCountY, 1);
364     }
365 
doDrawElementsBaseVertexBaseInstanceReset()366     void doDrawElementsBaseVertexBaseInstanceReset()
367     {
368         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
369         glDrawElementsInstanced(GL_TRIANGLES, 6 * kCountY, GL_UNSIGNED_SHORT,
370                                 reinterpret_cast<GLvoid *>(static_cast<uintptr_t>(0)), 1);
371     }
372 
doMultiDrawElementsInstancedBaseVertexBaseInstance()373     void doMultiDrawElementsInstancedBaseVertexBaseInstance()
374     {
375         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
376 
377         const GLsizei drawCount = kCountX * kCountY / 2;
378         const std::vector<GLsizei> counts(drawCount, 6);
379         const std::vector<GLsizei> instanceCounts(drawCount, 2);
380         const std::vector<GLvoid *> indices(drawCount, 0);
381         std::vector<GLint> baseVertices(drawCount);
382         std::vector<GLuint> baseInstances(drawCount);
383 
384         GLsizei b = 0;
385         for (uint32_t v = 0; v < kCountY; v++)
386         {
387             for (uint32_t i = 0; i < kCountX; i += 2)
388             {
389                 baseVertices[b]  = v * 4;
390                 baseInstances[b] = i;
391                 b++;
392             }
393         }
394 
395         glMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE(
396             GL_TRIANGLES, counts.data(), GL_UNSIGNED_SHORT, indices.data(), instanceCounts.data(),
397             baseVertices.data(), baseInstances.data(), drawCount);
398     }
399 
checkDrawResult(bool hasBaseVertex,bool oneColumn=false)400     void checkDrawResult(bool hasBaseVertex, bool oneColumn = false)
401     {
402         uint32_t numColums = oneColumn ? 1 : kCountX;
403         for (uint32_t y = 0; y < kCountY; ++y)
404         {
405             for (uint32_t x = 0; x < numColums; ++x)
406             {
407                 uint32_t center_x = x * kTilePixelSize[0] + kTilePixelSize[0] / 2;
408                 uint32_t center_y = y * kTilePixelSize[1] + kTilePixelSize[1] / 2;
409 
410                 EXPECT_PIXEL_NEAR(center_x - kPixelCheckSize[0] / 2,
411                                   center_y - kPixelCheckSize[1] / 2,
412                                   256.0 * (1.0 - (float)x / (float)kCountX),
413                                   256.0 * (1.0 - (float)y / (float)kCountY),
414                                   useBaseVertexBuiltin() && hasBaseVertex && !oneColumn
415                                       ? 256.0 * (1.0 - (float)y / (float)kCountY)
416                                       : 255,
417                                   255, 3);
418             }
419         }
420     }
421 
TearDown()422     void TearDown() override { ANGLETestBase::ANGLETestTearDown(); }
423 
requestDrawBaseVertexBaseInstanceExtension()424     bool requestDrawBaseVertexBaseInstanceExtension()
425     {
426         if (IsGLExtensionRequestable("GL_ANGLE_base_vertex_base_instance"))
427         {
428             glRequestExtensionANGLE("GL_ANGLE_base_vertex_base_instance");
429         }
430 
431         if (!IsGLExtensionEnabled("GL_ANGLE_base_vertex_base_instance"))
432         {
433             return false;
434         }
435 
436         if (IsGLExtensionRequestable("GL_ANGLE_base_vertex_base_instance_shader_builtin"))
437         {
438             glRequestExtensionANGLE("GL_ANGLE_base_vertex_base_instance_shader_builtin");
439         }
440 
441         return true;
442     }
443 
requestInstancedExtension()444     bool requestInstancedExtension()
445     {
446         if (IsGLExtensionRequestable("GL_ANGLE_instanced_arrays"))
447         {
448             glRequestExtensionANGLE("GL_ANGLE_instanced_arrays");
449         }
450 
451         if (!IsGLExtensionEnabled("GL_ANGLE_instanced_arrays"))
452         {
453             return false;
454         }
455 
456         return true;
457     }
458 
requestExtensions()459     bool requestExtensions()
460     {
461         if (getClientMajorVersion() <= 2)
462         {
463             if (!requestInstancedExtension())
464             {
465                 return false;
466             }
467         }
468         return requestDrawBaseVertexBaseInstanceExtension();
469     }
470 
471     // Used for base vertex base instance draw calls
472     std::vector<GLushort> mIndices;
473     std::vector<GLfloat> mVertices;
474     std::vector<GLfloat> mNonIndexedVertices;
475     // Used when gl_BaseInstance is not used
476     std::array<GLfloat, kCountX> mInstancedArrayId      = {};
477     std::array<GLfloat, kCountX> mInstancedArrayColorId = {};
478     // Used for regular draw calls without base vertex base instance
479     std::vector<GLushort> mRegularIndices;
480     GLint mPositionLoc         = 0;
481     GLuint mInstanceIDLoc      = 0;
482     GLuint mInstanceColorIDLoc = 0;
483 };
484 
485 using DrawBaseInstanceTestParams = std::
486     tuple<angle::PlatformParameters, BaseVertexOption, BaseInstanceOption, BufferDataUsageOption>;
487 
488 // The tests in DrawBaseInstanceTest check the correctness
489 // of the EXT_base_instance extension.
490 // gl_VertexID, gl_InstanceID, gl_BaseVertex, and gl_BaseInstance
491 // are checked by using them to select the color of the draw.
492 class DrawBaseInstanceTest : public ANGLETestBase,
493                              public ::testing::TestWithParam<DrawBaseInstanceTestParams>
494 {
495   protected:
DrawBaseInstanceTest()496     DrawBaseInstanceTest() : ANGLETestBase(std::get<0>(GetParam()))
497     {
498         setWindowWidth(kWidth);
499         setWindowHeight(kHeight);
500         setConfigRedBits(8);
501         setConfigGreenBits(8);
502         setConfigBlueBits(8);
503         setConfigAlphaBits(8);
504 
505         // Rects in the same column are within a vertex array, testing gl_VertexID, gl_BaseVertex
506         // Rects in the same row are drawn by instancing, testing gl_InstanceID, gl_BaseInstance
507 
508         mIndices = {0, 1, 2, 0, 2, 3};
509 
510         for (uint32_t y = 0; y < kCountY; ++y)
511         {
512             // v3 ---- v2
513             // |       |
514             // |       |
515             // v0 ---- v1
516 
517             const auto vs = getQuadVertices(0, y);
518 
519             for (const auto &v : vs)
520             {
521                 mVertices.insert(mVertices.end(), v.begin(), v.end());
522             }
523 
524             for (GLushort i : mIndices)
525             {
526                 mNonIndexedVertices.insert(mNonIndexedVertices.end(), vs[i].begin(), vs[i].end());
527             }
528         }
529 
530         mRegularIndices.resize(kCountY * mIndices.size());
531         for (uint32_t i = 0; i < kCountY; i++)
532         {
533             uint32_t oi = 6 * i;
534             uint32_t ov = 4 * i;
535             for (uint32_t j = 0; j < 6; j++)
536             {
537                 mRegularIndices[oi + j] = mIndices[j] + ov;
538             }
539         }
540 
541         std::iota(mInstancedArrayId.begin(), mInstancedArrayId.end(), 0.0f);
542         std::reverse_copy(mInstancedArrayId.begin(), mInstancedArrayId.end(),
543                           mInstancedArrayColorId.begin());
544     }
545 
SetUp()546     void SetUp() override { ANGLETestBase::ANGLETestSetUp(); }
547 
useBaseVertexBuiltin() const548     bool useBaseVertexBuiltin() const
549     {
550         return std::get<1>(GetParam()) == BaseVertexOption::UseBaseVertex;
551     }
552 
useBaseInstanceBuiltin() const553     bool useBaseInstanceBuiltin() const
554     {
555         return std::get<2>(GetParam()) == BaseInstanceOption::UseBaseInstance;
556     }
557 
getBufferDataUsage() const558     GLenum getBufferDataUsage() const
559     {
560         return std::get<3>(GetParam()) == BufferDataUsageOption::StaticDraw ? GL_STATIC_DRAW
561                                                                             : GL_DYNAMIC_DRAW;
562     }
563 
vertexShaderSource300(bool isDrawArrays,bool divisorTest)564     std::string vertexShaderSource300(bool isDrawArrays, bool divisorTest)
565     {
566         // Each color channel is to test the value of
567         // R: gl_InstanceID and gl_BaseInstance
568         // G: gl_VertexID and gl_BaseVertex
569         // B: gl_BaseVertex
570 
571         std::stringstream shader;
572         shader << ("#version 300 es\n")
573                << ("#extension GL_ANGLE_base_vertex_base_instance_shader_builtin : require\n")
574                << "#define kCountX " << kCountX << "\n"
575                << "#define kCountY " << kCountY << "\n"
576                << R"(
577 in vec2 vPosition;
578 )" << (useBaseInstanceBuiltin() ? "" : "in float vInstanceID;\n")
579                << (!divisorTest ? "" : "in float vInstanceColorID;\n") << R"(
580 out vec4 color;
581 void main()
582 {
583     const float xStep = 1.0 / float(kCountX);
584     const float yStep = 1.0 / float(kCountY);
585     float x_id = )"
586                << (useBaseInstanceBuiltin() ? " float(gl_InstanceID + gl_BaseInstance);"
587                                             : "vInstanceID;")
588                << "float x_color = "
589                << (divisorTest ? "xStep * (vInstanceColorID + 1.0f);" : " 1.0 - xStep * x_id;")
590                << R"(
591     float y_id = float(gl_VertexID / )"
592                << (isDrawArrays ? "6" : "4") << R"();
593 
594     color = vec4(
595         x_color,
596         1.0 - yStep * y_id,
597         )" << (useBaseVertexBuiltin() ? "1.0 - yStep * float(gl_BaseVertex) / 4.0" : "1.0")
598                << R"(,
599         1);
600 
601     mat3 transform = mat3(1.0);
602     transform[2][0] = x_id * xStep;
603 
604     gl_Position = vec4(transform * vec3(vPosition, 1.0) * 2.0 - 1.0, 1);
605 })";
606 
607         return shader.str();
608     }
609 
fragmentShaderSource300()610     std::string fragmentShaderSource300()
611     {
612         return
613             R"(#version 300 es
614 precision mediump float;
615 in vec4 color;
616 out vec4 o_color;
617 void main()
618 {
619     o_color = color;
620 })";
621     }
622 
setupProgram(GLProgram & program,bool isDrawArrays=true,bool isDivisorTest=false)623     void setupProgram(GLProgram &program, bool isDrawArrays = true, bool isDivisorTest = false)
624     {
625         program.makeRaster(vertexShaderSource300(isDrawArrays, isDivisorTest).c_str(),
626                            fragmentShaderSource300().c_str());
627         EXPECT_GL_NO_ERROR();
628         ASSERT_TRUE(program.valid());
629         glUseProgram(program);
630         mPositionLoc = glGetAttribLocation(program, "vPosition");
631         if (!useBaseInstanceBuiltin())
632         {
633             mInstanceIDLoc      = glGetAttribLocation(program, "vInstanceID");
634             mInstanceColorIDLoc = glGetAttribLocation(program, "vInstanceColorID");
635         }
636     }
637 
setupNonIndexedBuffers(GLBuffer & vertexBuffer)638     void setupNonIndexedBuffers(GLBuffer &vertexBuffer)
639     {
640         glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
641         glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mNonIndexedVertices.size(),
642                      mNonIndexedVertices.data(), getBufferDataUsage());
643 
644         ASSERT_GL_NO_ERROR();
645     }
646 
setupIndexedBuffers(GLBuffer & vertexBuffer,GLBuffer & indexBuffer)647     void setupIndexedBuffers(GLBuffer &vertexBuffer, GLBuffer &indexBuffer)
648     {
649         glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
650         glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mVertices.size(), mVertices.data(),
651                      getBufferDataUsage());
652 
653         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
654         glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * mIndices.size(), mIndices.data(),
655                      getBufferDataUsage());
656 
657         ASSERT_GL_NO_ERROR();
658     }
659 
setupInstanceIDBuffer(GLBuffer & instanceIDBuffer)660     void setupInstanceIDBuffer(GLBuffer &instanceIDBuffer)
661     {
662         glBindBuffer(GL_ARRAY_BUFFER, instanceIDBuffer);
663         glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mInstancedArrayId.size(),
664                      mInstancedArrayId.data(), getBufferDataUsage());
665 
666         ASSERT_GL_NO_ERROR();
667     }
668 
setupInstanceColorIDBuffer(GLBuffer & instanceIDBuffer)669     void setupInstanceColorIDBuffer(GLBuffer &instanceIDBuffer)
670     {
671         glBindBuffer(GL_ARRAY_BUFFER, instanceIDBuffer);
672         glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mInstancedArrayColorId.size(),
673                      mInstancedArrayColorId.data(), getBufferDataUsage());
674 
675         ASSERT_GL_NO_ERROR();
676     }
677 
setupRegularIndexedBuffer(GLBuffer & indexBuffer)678     void setupRegularIndexedBuffer(GLBuffer &indexBuffer)
679     {
680         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
681         glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * mRegularIndices.size(),
682                      mRegularIndices.data(), getBufferDataUsage());
683 
684         ASSERT_GL_NO_ERROR();
685     }
686 
setupPositionVertexAttribPointer()687     void setupPositionVertexAttribPointer()
688     {
689         glEnableVertexAttribArray(mPositionLoc);
690         glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
691     }
692 
setupInstanceIDVertexAttribPointer(GLuint instanceIDLoc)693     void setupInstanceIDVertexAttribPointer(GLuint instanceIDLoc)
694     {
695         glEnableVertexAttribArray(instanceIDLoc);
696         glVertexAttribPointer(instanceIDLoc, 1, GL_FLOAT, GL_FALSE, 0, 0);
697         glVertexAttribDivisor(instanceIDLoc, 1);
698     }
699 
doDrawArraysInstancedBaseInstance()700     void doDrawArraysInstancedBaseInstance()
701     {
702         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
703 
704         const uint32_t countPerDraw = kCountY * 6;
705 
706         for (uint32_t i = 0; i < kCountX; i += 2)
707         {
708             glDrawArraysInstancedBaseInstanceEXT(GL_TRIANGLES, 0, countPerDraw, 2, i);
709         }
710     }
711 
doDrawElementsInstancedBaseInstance()712     void doDrawElementsInstancedBaseInstance()
713     {
714         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
715 
716         const uint32_t countPerDraw = 6;
717 
718         for (uint32_t v = 0; v < kCountY; v++)
719         {
720             for (uint32_t i = 0; i < kCountX; i += 2)
721             {
722                 glDrawElementsInstancedBaseInstanceEXT(GL_TRIANGLES, countPerDraw,
723                                                        GL_UNSIGNED_SHORT,
724                                                        (void *)(v * 6 * sizeof(GLushort)), 2, i);
725             }
726         }
727     }
728 
doDrawElementsInstancedBaseVertexBaseInstance()729     void doDrawElementsInstancedBaseVertexBaseInstance()
730     {
731         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
732 
733         const uint32_t countPerDraw = 6;
734 
735         for (uint32_t v = 0; v < kCountY; v++)
736         {
737             for (uint32_t i = 0; i < kCountX; i += 2)
738             {
739                 glDrawElementsInstancedBaseVertexBaseInstanceEXT(
740                     GL_TRIANGLES, countPerDraw, GL_UNSIGNED_SHORT,
741                     reinterpret_cast<GLvoid *>(static_cast<uintptr_t>(0)), 2, v * 4, i);
742             }
743         }
744     }
745 
746     // Call this after the *BaseInstance draw call to check
747     // if value of BaseInstance is reset to zero
doDrawArraysBaseInstanceReset()748     void doDrawArraysBaseInstanceReset()
749     {
750         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
751         glDrawArraysInstanced(GL_TRIANGLES, 0, 6 * kCountY, 1);
752     }
753 
doDrawElementsInstancedBaseInstanceReset()754     void doDrawElementsInstancedBaseInstanceReset()
755     {
756         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
757         glDrawElementsInstanced(GL_TRIANGLES, 6 * kCountY, GL_UNSIGNED_SHORT,
758                                 reinterpret_cast<GLvoid *>(static_cast<uintptr_t>(0)), 1);
759     }
760 
doDrawElementsBaseVertexBaseInstanceReset()761     void doDrawElementsBaseVertexBaseInstanceReset()
762     {
763         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
764         glDrawElementsInstanced(GL_TRIANGLES, 6 * kCountY, GL_UNSIGNED_SHORT,
765                                 reinterpret_cast<GLvoid *>(static_cast<uintptr_t>(0)), 1);
766     }
767 
checkDrawResult(bool hasBaseVertex,bool oneColumn=false)768     void checkDrawResult(bool hasBaseVertex, bool oneColumn = false)
769     {
770         uint32_t numColums = oneColumn ? 1 : kCountX;
771         for (uint32_t y = 0; y < kCountY; ++y)
772         {
773             for (uint32_t x = 0; x < numColums; ++x)
774             {
775                 uint32_t center_x = x * kTilePixelSize[0] + kTilePixelSize[0] / 2;
776                 uint32_t center_y = y * kTilePixelSize[1] + kTilePixelSize[1] / 2;
777 
778                 EXPECT_PIXEL_NEAR(center_x - kPixelCheckSize[0] / 2,
779                                   center_y - kPixelCheckSize[1] / 2,
780                                   256.0 * (1.0 - (float)x / (float)kCountX),
781                                   256.0 * (1.0 - (float)y / (float)kCountY),
782                                   useBaseVertexBuiltin() && hasBaseVertex && !oneColumn
783                                       ? 256.0 * (1.0 - (float)y / (float)kCountY)
784                                       : 255,
785                                   255, 3);
786             }
787         }
788     }
789 
TearDown()790     void TearDown() override { ANGLETestBase::ANGLETestTearDown(); }
791 
requestExtensions()792     bool requestExtensions()
793     {
794         if (IsGLExtensionRequestable("GL_ANGLE_base_vertex_base_instance_shader_builtin"))
795         {
796             glRequestExtensionANGLE("GL_ANGLE_base_vertex_base_instance_shader_builtin");
797         }
798 
799         if (!IsGLExtensionEnabled("GL_ANGLE_base_vertex_base_instance_shader_builtin"))
800         {
801             return false;
802         }
803 
804         return EnsureGLExtensionEnabled("GL_EXT_base_instance");
805     }
806 
807     // Used for base vertex base instance draw calls
808     std::vector<GLushort> mIndices;
809     std::vector<GLfloat> mVertices;
810     std::vector<GLfloat> mNonIndexedVertices;
811     // Used when gl_BaseInstance is not used
812     std::array<GLfloat, kCountX> mInstancedArrayId      = {};
813     std::array<GLfloat, kCountX> mInstancedArrayColorId = {};
814     // Used for regular draw calls without base vertex base instance
815     std::vector<GLushort> mRegularIndices;
816     GLint mPositionLoc         = 0;
817     GLuint mInstanceIDLoc      = 0;
818     GLuint mInstanceColorIDLoc = 0;
819 };
820 
821 // Tests that compile a program with the extension succeeds
TEST_P(DrawBaseVertexBaseInstanceTest,CanCompile)822 TEST_P(DrawBaseVertexBaseInstanceTest, CanCompile)
823 {
824     ANGLE_SKIP_TEST_IF(!requestExtensions());
825     GLProgram p0;
826     setupProgram(p0, true, false);
827     GLProgram p1;
828     setupProgram(p1, true, true);
829     GLProgram p2;
830     setupProgram(p2, false, false);
831     GLProgram p3;
832     setupProgram(p3, false, true);
833 }
834 
835 // Tests if baseInstance works properly with instanced array with non-zero divisor
TEST_P(DrawBaseVertexBaseInstanceTest,BaseInstanceDivisor)836 TEST_P(DrawBaseVertexBaseInstanceTest, BaseInstanceDivisor)
837 {
838     ANGLE_SKIP_TEST_IF(!requestExtensions());
839     ANGLE_SKIP_TEST_IF(useBaseInstanceBuiltin());
840 
841     GLProgram program;
842     setupProgram(program, true, false, true);
843 
844     GLBuffer nonIndexedVertexBuffer;
845     setupNonIndexedBuffers(nonIndexedVertexBuffer);
846     setupPositionVertexAttribPointer();
847 
848     GLBuffer instanceIDBuffer;
849     GLBuffer instanceColorIDBuffer;
850 
851     setupInstanceIDBuffer(instanceIDBuffer);
852     setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
853     setupInstanceColorIDBuffer(instanceColorIDBuffer);
854     setupInstanceIDVertexAttribPointer(mInstanceColorIDLoc);
855 
856     doDrawArraysInstancedBaseInstance();
857     EXPECT_GL_NO_ERROR();
858     checkDrawResult(false);
859 
860     doDrawArraysBaseInstanceReset();
861     EXPECT_GL_NO_ERROR();
862     checkDrawResult(false, true);
863 
864     GLProgram programIndexed;
865     setupProgram(programIndexed, false, false, true);
866 
867     GLBuffer indexBuffer;
868     GLBuffer vertexBuffer;
869     setupIndexedBuffers(vertexBuffer, indexBuffer);
870     setupPositionVertexAttribPointer();
871 
872     glBindBuffer(GL_ARRAY_BUFFER, instanceIDBuffer);
873     setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
874     glBindBuffer(GL_ARRAY_BUFFER, instanceColorIDBuffer);
875     setupInstanceIDVertexAttribPointer(mInstanceColorIDLoc);
876 
877     doDrawElementsInstancedBaseVertexBaseInstance();
878     EXPECT_GL_NO_ERROR();
879     checkDrawResult(true);
880 
881     setupRegularIndexedBuffer(indexBuffer);
882     doDrawElementsBaseVertexBaseInstanceReset();
883     EXPECT_GL_NO_ERROR();
884     checkDrawResult(false, true);
885 }
886 
887 // Tests basic functionality of glDrawArraysInstancedBaseInstanceANGLE
TEST_P(DrawBaseVertexBaseInstanceTest,DrawArraysInstancedBaseInstance)888 TEST_P(DrawBaseVertexBaseInstanceTest, DrawArraysInstancedBaseInstance)
889 {
890     // TODO(shrekshao): Temporarily skip this test
891     // before we could try updating win AMD bot driver version
892     // after Lab team fixed issues with ssh into bot machines
893     // Currently this test fail on certain Win7/Win2008Server AMD GPU
894     // with driver version 23.20.185.235 when using OpenGL backend.
895     // This failure couldn't be produced on local Win10 AMD machine with latest driver installed
896     // Same for the MultiDrawArraysInstancedBaseInstance test
897     if (IsAMD() && IsWindows() && IsDesktopOpenGL())
898     {
899         SystemInfo *systemInfo = GetTestSystemInfo();
900         if (!systemInfo->gpus.empty())
901         {
902             ANGLE_SKIP_TEST_IF(0x6613 == systemInfo->gpus[systemInfo->activeGPUIndex].deviceId);
903         }
904     }
905 
906     ANGLE_SKIP_TEST_IF(!requestExtensions());
907 
908     GLProgram program;
909     setupProgram(program, true);
910 
911     GLBuffer vertexBuffer;
912     setupNonIndexedBuffers(vertexBuffer);
913     setupPositionVertexAttribPointer();
914 
915     GLBuffer instanceIDBuffer;
916     if (!useBaseInstanceBuiltin())
917     {
918         setupInstanceIDBuffer(instanceIDBuffer);
919         setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
920     }
921 
922     doDrawArraysInstancedBaseInstance();
923     EXPECT_GL_NO_ERROR();
924     checkDrawResult(false);
925 
926     doDrawArraysBaseInstanceReset();
927     EXPECT_GL_NO_ERROR();
928     checkDrawResult(false, true);
929 }
930 
931 // Tests basic functionality of glMultiDrawArraysInstancedBaseInstance
TEST_P(DrawBaseVertexBaseInstanceTest,MultiDrawArraysInstancedBaseInstance)932 TEST_P(DrawBaseVertexBaseInstanceTest, MultiDrawArraysInstancedBaseInstance)
933 {
934     if (IsAMD() && IsWindows() && IsDesktopOpenGL())
935     {
936         SystemInfo *systemInfo = GetTestSystemInfo();
937         if (!(systemInfo->activeGPUIndex < 0 || systemInfo->gpus.empty()))
938         {
939             ANGLE_SKIP_TEST_IF(0x6613 == systemInfo->gpus[systemInfo->activeGPUIndex].deviceId);
940         }
941     }
942 
943     ANGLE_SKIP_TEST_IF(!requestExtensions());
944 
945     GLProgram program;
946     setupProgram(program, true, true);
947 
948     GLBuffer vertexBuffer;
949     setupNonIndexedBuffers(vertexBuffer);
950     setupPositionVertexAttribPointer();
951 
952     GLBuffer instanceIDBuffer;
953     if (!useBaseInstanceBuiltin())
954     {
955         setupInstanceIDBuffer(instanceIDBuffer);
956         setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
957     }
958 
959     doMultiDrawArraysInstancedBaseInstance();
960     EXPECT_GL_NO_ERROR();
961     checkDrawResult(false);
962 
963     doDrawArraysBaseInstanceReset();
964     EXPECT_GL_NO_ERROR();
965     checkDrawResult(false, true);
966 }
967 
968 // Tests basic functionality of glDrawElementsInstancedBaseVertexBaseInstanceANGLE
TEST_P(DrawBaseVertexBaseInstanceTest,DrawElementsInstancedBaseVertexBaseInstance)969 TEST_P(DrawBaseVertexBaseInstanceTest, DrawElementsInstancedBaseVertexBaseInstance)
970 {
971     ANGLE_SKIP_TEST_IF(!requestExtensions());
972 
973     GLProgram program;
974     setupProgram(program, false);
975 
976     GLBuffer indexBuffer;
977     GLBuffer vertexBuffer;
978     setupIndexedBuffers(vertexBuffer, indexBuffer);
979     setupPositionVertexAttribPointer();
980 
981     GLBuffer instanceIDBuffer;
982     if (!useBaseInstanceBuiltin())
983     {
984         setupInstanceIDBuffer(instanceIDBuffer);
985         setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
986     }
987 
988     doDrawElementsInstancedBaseVertexBaseInstance();
989     EXPECT_GL_NO_ERROR();
990     checkDrawResult(true);
991 
992     setupRegularIndexedBuffer(indexBuffer);
993     doDrawElementsBaseVertexBaseInstanceReset();
994     EXPECT_GL_NO_ERROR();
995     checkDrawResult(true, true);
996 }
997 
998 // Tests basic functionality of glMultiDrawElementsInstancedBaseVertexBaseInstance
TEST_P(DrawBaseVertexBaseInstanceTest,MultiDrawElementsInstancedBaseVertexBaseInstance)999 TEST_P(DrawBaseVertexBaseInstanceTest, MultiDrawElementsInstancedBaseVertexBaseInstance)
1000 {
1001     ANGLE_SKIP_TEST_IF(!requestExtensions());
1002 
1003     GLProgram program;
1004     setupProgram(program, false, true);
1005 
1006     GLBuffer indexBuffer;
1007     GLBuffer vertexBuffer;
1008     setupIndexedBuffers(vertexBuffer, indexBuffer);
1009     setupPositionVertexAttribPointer();
1010 
1011     GLBuffer instanceIDBuffer;
1012     if (!useBaseInstanceBuiltin())
1013     {
1014         setupInstanceIDBuffer(instanceIDBuffer);
1015         setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
1016     }
1017 
1018     doMultiDrawElementsInstancedBaseVertexBaseInstance();
1019     EXPECT_GL_NO_ERROR();
1020     checkDrawResult(true);
1021 
1022     setupRegularIndexedBuffer(indexBuffer);
1023     doDrawElementsBaseVertexBaseInstanceReset();
1024     EXPECT_GL_NO_ERROR();
1025     checkDrawResult(true, true);
1026 }
1027 
1028 // Tests if baseInstance works properly with instanced array with non-zero divisor
TEST_P(DrawBaseInstanceTest,BaseInstanceDivisor)1029 TEST_P(DrawBaseInstanceTest, BaseInstanceDivisor)
1030 {
1031     ANGLE_SKIP_TEST_IF(!requestExtensions());
1032     ANGLE_SKIP_TEST_IF(useBaseInstanceBuiltin());
1033 
1034     GLProgram program;
1035     setupProgram(program, true, true);
1036 
1037     GLBuffer nonIndexedVertexBuffer;
1038     setupNonIndexedBuffers(nonIndexedVertexBuffer);
1039     setupPositionVertexAttribPointer();
1040 
1041     GLBuffer instanceIDBuffer;
1042     GLBuffer instanceColorIDBuffer;
1043 
1044     setupInstanceIDBuffer(instanceIDBuffer);
1045     setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
1046     setupInstanceColorIDBuffer(instanceColorIDBuffer);
1047     setupInstanceIDVertexAttribPointer(mInstanceColorIDLoc);
1048 
1049     doDrawArraysInstancedBaseInstance();
1050     EXPECT_GL_NO_ERROR();
1051     checkDrawResult(false);
1052 
1053     doDrawArraysBaseInstanceReset();
1054     EXPECT_GL_NO_ERROR();
1055     checkDrawResult(false, true);
1056 
1057     GLProgram programIndexed;
1058     setupProgram(programIndexed, false, true);
1059 
1060     GLBuffer indexBuffer;
1061     GLBuffer vertexBuffer;
1062     setupIndexedBuffers(vertexBuffer, indexBuffer);
1063     setupPositionVertexAttribPointer();
1064 
1065     glBindBuffer(GL_ARRAY_BUFFER, instanceIDBuffer);
1066     setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
1067     glBindBuffer(GL_ARRAY_BUFFER, instanceColorIDBuffer);
1068     setupInstanceIDVertexAttribPointer(mInstanceColorIDLoc);
1069 
1070     doDrawElementsInstancedBaseVertexBaseInstance();
1071     EXPECT_GL_NO_ERROR();
1072     checkDrawResult(true);
1073 
1074     setupRegularIndexedBuffer(indexBuffer);
1075     doDrawElementsBaseVertexBaseInstanceReset();
1076     EXPECT_GL_NO_ERROR();
1077     checkDrawResult(false, true);
1078 }
1079 
1080 // Tests basic functionality of glDrawArraysInstancedBaseInstanceEXT
TEST_P(DrawBaseInstanceTest,DrawArraysInstancedBaseInstance)1081 TEST_P(DrawBaseInstanceTest, DrawArraysInstancedBaseInstance)
1082 {
1083     // This test fails on certain Win7/Win2008Server AMD GPU
1084     // with driver version 23.20.185.235 when using OpenGL backend.
1085     // See comments under the ANGLE test of DrawArraysInstancedBaseInstance above.
1086     if (IsAMD() && IsWindows() && IsDesktopOpenGL())
1087     {
1088         SystemInfo *systemInfo = GetTestSystemInfo();
1089         if (!systemInfo->gpus.empty())
1090         {
1091             ANGLE_SKIP_TEST_IF(0x6613 == systemInfo->gpus[systemInfo->activeGPUIndex].deviceId);
1092         }
1093     }
1094 
1095     ANGLE_SKIP_TEST_IF(!requestExtensions());
1096 
1097     GLProgram program;
1098     setupProgram(program);
1099 
1100     GLBuffer vertexBuffer;
1101     setupNonIndexedBuffers(vertexBuffer);
1102     setupPositionVertexAttribPointer();
1103 
1104     GLBuffer instanceIDBuffer;
1105     if (!useBaseInstanceBuiltin())
1106     {
1107         setupInstanceIDBuffer(instanceIDBuffer);
1108         setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
1109     }
1110 
1111     doDrawArraysInstancedBaseInstance();
1112     EXPECT_GL_NO_ERROR();
1113     checkDrawResult(false);
1114 
1115     doDrawArraysBaseInstanceReset();
1116     EXPECT_GL_NO_ERROR();
1117     checkDrawResult(false, true);
1118 }
1119 
1120 // Tests basic functionality of glDrawElementsInstancedBaseInstanceEXT
TEST_P(DrawBaseInstanceTest,DrawElementsInstancedBaseInstance)1121 TEST_P(DrawBaseInstanceTest, DrawElementsInstancedBaseInstance)
1122 {
1123     ANGLE_SKIP_TEST_IF(!requestExtensions());
1124 
1125     GLProgram program;
1126     setupProgram(program, false);
1127 
1128     GLBuffer vertexBuffer;
1129     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1130     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mVertices.size(), mVertices.data(),
1131                  getBufferDataUsage());
1132     EXPECT_GL_NO_ERROR();
1133     setupPositionVertexAttribPointer();
1134 
1135     GLBuffer indexBuffer;
1136     setupRegularIndexedBuffer(indexBuffer);
1137 
1138     GLBuffer instanceIDBuffer;
1139     if (!useBaseInstanceBuiltin())
1140     {
1141         setupInstanceIDBuffer(instanceIDBuffer);
1142         setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
1143     }
1144 
1145     doDrawElementsInstancedBaseInstance();
1146     EXPECT_GL_NO_ERROR();
1147     checkDrawResult(false);
1148 
1149     doDrawElementsInstancedBaseInstanceReset();
1150     EXPECT_GL_NO_ERROR();
1151     checkDrawResult(false, true);
1152 }
1153 
1154 // Tests basic functionality of glDrawElementsInstancedBaseVertexBaseInstanceEXT
TEST_P(DrawBaseInstanceTest,DrawElementsInstancedBaseVertexBaseInstance)1155 TEST_P(DrawBaseInstanceTest, DrawElementsInstancedBaseVertexBaseInstance)
1156 {
1157     ANGLE_SKIP_TEST_IF(!requestExtensions());
1158 
1159     GLProgram program;
1160     setupProgram(program, false);
1161 
1162     GLBuffer indexBuffer;
1163     GLBuffer vertexBuffer;
1164     setupIndexedBuffers(vertexBuffer, indexBuffer);
1165     setupPositionVertexAttribPointer();
1166 
1167     GLBuffer instanceIDBuffer;
1168     if (!useBaseInstanceBuiltin())
1169     {
1170         setupInstanceIDBuffer(instanceIDBuffer);
1171         setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
1172     }
1173 
1174     doDrawElementsInstancedBaseVertexBaseInstance();
1175     EXPECT_GL_NO_ERROR();
1176     checkDrawResult(true);
1177 
1178     setupRegularIndexedBuffer(indexBuffer);
1179     doDrawElementsBaseVertexBaseInstanceReset();
1180     EXPECT_GL_NO_ERROR();
1181     checkDrawResult(true, true);
1182 }
1183 
1184 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrawBaseVertexBaseInstanceTest);
1185 
1186 #define ANGLE_ALL_BASEVERTEXBASEINTANCE_TEST_PLATFORMS_ES3                                 \
1187     ES3_D3D11().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions),                  \
1188         ES3_OPENGL().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions),             \
1189         ES3_OPENGLES().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions),           \
1190         ES3_VULKAN().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions),             \
1191         ES3_VULKAN_SWIFTSHADER().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions), \
1192         ES3_METAL().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions)
1193 
1194 ANGLE_INSTANTIATE_TEST_COMBINE_3(
1195     DrawBaseVertexBaseInstanceTest,
1196     PrintToStringParamName(),
1197     testing::Values(BaseVertexOption::NoBaseVertex, BaseVertexOption::UseBaseVertex),
1198     testing::Values(BaseInstanceOption::NoBaseInstance, BaseInstanceOption::UseBaseInstance),
1199     testing::Values(BufferDataUsageOption::StaticDraw, BufferDataUsageOption::DynamicDraw),
1200     ANGLE_ALL_BASEVERTEXBASEINTANCE_TEST_PLATFORMS_ES3);
1201 
1202 ANGLE_INSTANTIATE_TEST_COMBINE_3(
1203     DrawBaseInstanceTest,
1204     PrintToStringParamName(),
1205     testing::Values(BaseVertexOption::NoBaseVertex, BaseVertexOption::UseBaseVertex),
1206     testing::Values(BaseInstanceOption::NoBaseInstance, BaseInstanceOption::UseBaseInstance),
1207     testing::Values(BufferDataUsageOption::StaticDraw, BufferDataUsageOption::DynamicDraw),
1208     ANGLE_ALL_BASEVERTEXBASEINTANCE_TEST_PLATFORMS_ES3);
1209 
1210 }  // namespace
1211