• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
9 #include "gpu_info_util/SystemInfo.h"
10 #include "test_utils/ANGLETest.h"
11 #include "test_utils/gl_raii.h"
12 
13 #include <numeric>
14 
15 using namespace angle;
16 
17 namespace
18 {
19 
20 // Create a kWidth * kHeight canvas equally split into kCountX * kCountY tiles
21 // each containing a quad partially covering each tile
22 constexpr uint32_t kWidth                  = 256;
23 constexpr uint32_t kHeight                 = 256;
24 constexpr uint32_t kCountX                 = 8;
25 constexpr uint32_t kCountY                 = 8;
26 constexpr std::array<GLfloat, 2> kTileSize = {
27     1.f / static_cast<GLfloat>(kCountX),
28     1.f / static_cast<GLfloat>(kCountY),
29 };
30 constexpr std::array<uint32_t, 2> kTilePixelSize  = {kWidth / kCountX, kHeight / kCountY};
31 constexpr std::array<GLfloat, 2> kQuadRadius      = {0.25f * kTileSize[0], 0.25f * kTileSize[1]};
32 constexpr std::array<uint32_t, 2> kPixelCheckSize = {
33     static_cast<uint32_t>(kQuadRadius[0] * kWidth),
34     static_cast<uint32_t>(kQuadRadius[1] * kHeight)};
35 
getTileCenter(uint32_t x,uint32_t y)36 constexpr std::array<GLfloat, 2> getTileCenter(uint32_t x, uint32_t y)
37 {
38     return {
39         kTileSize[0] * (0.5f + static_cast<GLfloat>(x)),
40         kTileSize[1] * (0.5f + static_cast<GLfloat>(y)),
41     };
42 }
getQuadVertices(uint32_t x,uint32_t y)43 constexpr std::array<std::array<GLfloat, 3>, 4> getQuadVertices(uint32_t x, uint32_t y)
44 {
45     const auto center = getTileCenter(x, y);
46     return {
47         std::array<GLfloat, 3>{center[0] - kQuadRadius[0], center[1] - kQuadRadius[1], 0.0f},
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     };
52 }
53 
54 enum class BaseVertexOption
55 {
56     NoBaseVertex,
57     UseBaseVertex
58 };
59 
60 enum class BaseInstanceOption
61 {
62     NoBaseInstance,
63     UseBaseInstance
64 };
65 
66 using DrawBaseVertexBaseInstanceTestParams =
67     std::tuple<angle::PlatformParameters, BaseVertexOption, BaseInstanceOption>;
68 
69 struct PrintToStringParamName
70 {
operator ()__anon52e0881c0111::PrintToStringParamName71     std::string operator()(
72         const ::testing::TestParamInfo<DrawBaseVertexBaseInstanceTestParams> &info) const
73     {
74         ::std::stringstream ss;
75         ss << (std::get<2>(info.param) == BaseInstanceOption::UseBaseInstance ? "UseBaseInstance_"
76                                                                               : "")
77            << (std::get<1>(info.param) == BaseVertexOption::UseBaseVertex ? "UseBaseVertex_" : "")
78            << std::get<0>(info.param);
79         return ss.str();
80     }
81 };
82 
83 // These tests check correctness of the ANGLE_base_vertex_base_instance extension.
84 // An array of quads is drawn across the screen.
85 // gl_VertexID, gl_InstanceID, gl_BaseVertex, and gl_BaseInstance
86 // are checked by using them to select the color of the draw.
87 class DrawBaseVertexBaseInstanceTest
88     : public ANGLETestBase,
89       public ::testing::TestWithParam<DrawBaseVertexBaseInstanceTestParams>
90 {
91   protected:
DrawBaseVertexBaseInstanceTest()92     DrawBaseVertexBaseInstanceTest() : ANGLETestBase(std::get<0>(GetParam()))
93     {
94         setWindowWidth(kWidth);
95         setWindowHeight(kHeight);
96         setConfigRedBits(8);
97         setConfigGreenBits(8);
98         setConfigBlueBits(8);
99         setConfigAlphaBits(8);
100 
101         // Rects in the same column are within a vertex array, testing gl_VertexID, gl_BaseVertex
102         // Rects in the same row are drawn by instancing, testing gl_InstanceID, gl_BaseInstance
103 
104         mIndices = {0, 1, 2, 0, 2, 3};
105 
106         for (uint32_t y = 0; y < kCountY; ++y)
107         {
108             // v3 ---- v2
109             // |       |
110             // |       |
111             // v0 ---- v1
112 
113             const auto vs = getQuadVertices(0, y);
114 
115             for (const auto &v : vs)
116             {
117                 mVertices.insert(mVertices.end(), v.begin(), v.end());
118             }
119 
120             for (GLushort i : mIndices)
121             {
122                 mNonIndexedVertices.insert(mNonIndexedVertices.end(), vs[i].begin(), vs[i].end());
123             }
124         }
125 
126         mRegularIndices.resize(kCountY * mIndices.size());
127         for (uint32_t i = 0; i < kCountY; i++)
128         {
129             uint32_t oi = 6 * i;
130             uint32_t ov = 4 * i;
131             for (uint32_t j = 0; j < 6; j++)
132             {
133                 mRegularIndices[oi + j] = mIndices[j] + ov;
134             }
135         }
136 
137         std::iota(mInstancedArrayId.begin(), mInstancedArrayId.end(), 0.0f);
138         std::reverse_copy(mInstancedArrayId.begin(), mInstancedArrayId.end(),
139                           mInstancedArrayColorId.begin());
140     }
141 
SetUp()142     void SetUp() override { ANGLETestBase::ANGLETestSetUp(); }
143 
useBaseVertexBuiltin() const144     bool useBaseVertexBuiltin() const
145     {
146         return std::get<1>(GetParam()) == BaseVertexOption::UseBaseVertex;
147     }
148 
useBaseInstanceBuiltin() const149     bool useBaseInstanceBuiltin() const
150     {
151         return std::get<2>(GetParam()) == BaseInstanceOption::UseBaseInstance;
152     }
153 
vertexShaderSource300(bool isDrawArrays,bool isMultiDraw,bool divisorTest)154     std::string vertexShaderSource300(bool isDrawArrays, bool isMultiDraw, bool divisorTest)
155     {
156         // Each color channel is to test the value of
157         // R: gl_InstanceID and gl_BaseInstance
158         // G: gl_VertexID and gl_BaseVertex
159         // B: gl_BaseVertex
160 
161         std::stringstream shader;
162         shader << ("#version 300 es\n")
163                << (isMultiDraw ? "#extension GL_ANGLE_multi_draw : require\n" : "")
164                << ("#extension GL_ANGLE_base_vertex_base_instance : require\n")
165                << "#define kCountX " << kCountX << "\n"
166                << "#define kCountY " << kCountY << "\n"
167                << R"(
168 in vec2 vPosition;
169 )" << (useBaseInstanceBuiltin() ? "" : "in float vInstanceID;\n")
170                << (!divisorTest ? "" : "in float vInstanceColorID;\n") << R"(
171 out vec4 color;
172 void main()
173 {
174     const float xStep = 1.0 / float(kCountX);
175     const float yStep = 1.0 / float(kCountY);
176     float x_id = )"
177                << (useBaseInstanceBuiltin() ? " float(gl_InstanceID + gl_BaseInstance);"
178                                             : "vInstanceID;")
179                << "float x_color = "
180                << (divisorTest ? "xStep * (vInstanceColorID + 1.0f);" : " 1.0 - xStep * x_id;")
181                << R"(
182     float y_id = floor(float(gl_VertexID) / )"
183                << (isDrawArrays ? "6.0" : "4.0") << R"( + 0.01);
184 
185     color = vec4(
186         x_color,
187         1.0 - yStep * y_id,
188         )" << (useBaseVertexBuiltin() ? "1.0 - yStep * float(gl_BaseVertex) / 4.0" : "1.0")
189                << R"(,
190         1);
191 
192     mat3 transform = mat3(1.0);
193     transform[2][0] = x_id * xStep;
194 
195     gl_Position = vec4(transform * vec3(vPosition, 1.0) * 2.0 - 1.0, 1);
196 })";
197 
198         return shader.str();
199     }
200 
fragmentShaderSource300()201     std::string fragmentShaderSource300()
202     {
203         return
204             R"(#version 300 es
205 precision mediump float;
206 in vec4 color;
207 out vec4 o_color;
208 void main()
209 {
210     o_color = color;
211 })";
212     }
213 
setupProgram(GLProgram & program,bool isDrawArrays=true,bool isMultiDraw=false,bool isDivisorTest=false)214     void setupProgram(GLProgram &program,
215                       bool isDrawArrays  = true,
216                       bool isMultiDraw   = false,
217                       bool isDivisorTest = false)
218     {
219         program.makeRaster(vertexShaderSource300(isDrawArrays, isMultiDraw, isDivisorTest).c_str(),
220                            fragmentShaderSource300().c_str());
221         EXPECT_GL_NO_ERROR();
222         ASSERT_TRUE(program.valid());
223         glUseProgram(program.get());
224         mPositionLoc = glGetAttribLocation(program.get(), "vPosition");
225         if (!useBaseInstanceBuiltin())
226         {
227             mInstanceIDLoc      = glGetAttribLocation(program.get(), "vInstanceID");
228             mInstanceColorIDLoc = glGetAttribLocation(program.get(), "vInstanceColorID");
229         }
230     }
231 
setupNonIndexedBuffers(GLBuffer & vertexBuffer)232     void setupNonIndexedBuffers(GLBuffer &vertexBuffer)
233     {
234         glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
235         glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mNonIndexedVertices.size(),
236                      mNonIndexedVertices.data(), GL_STATIC_DRAW);
237 
238         ASSERT_GL_NO_ERROR();
239     }
240 
setupIndexedBuffers(GLBuffer & vertexBuffer,GLBuffer & indexBuffer)241     void setupIndexedBuffers(GLBuffer &vertexBuffer, GLBuffer &indexBuffer)
242     {
243         glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
244         glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mVertices.size(), mVertices.data(),
245                      GL_STATIC_DRAW);
246 
247         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
248         glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * mIndices.size(), mIndices.data(),
249                      GL_STATIC_DRAW);
250 
251         ASSERT_GL_NO_ERROR();
252     }
253 
setupInstanceIDBuffer(GLBuffer & instanceIDBuffer)254     void setupInstanceIDBuffer(GLBuffer &instanceIDBuffer)
255     {
256         glBindBuffer(GL_ARRAY_BUFFER, instanceIDBuffer);
257         glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mInstancedArrayId.size(),
258                      mInstancedArrayId.data(), GL_STATIC_DRAW);
259 
260         ASSERT_GL_NO_ERROR();
261     }
262 
setupInstanceColorIDBuffer(GLBuffer & instanceIDBuffer)263     void setupInstanceColorIDBuffer(GLBuffer &instanceIDBuffer)
264     {
265         glBindBuffer(GL_ARRAY_BUFFER, instanceIDBuffer);
266         glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mInstancedArrayColorId.size(),
267                      mInstancedArrayColorId.data(), GL_STATIC_DRAW);
268 
269         ASSERT_GL_NO_ERROR();
270     }
271 
setupRegularIndexedBuffer(GLBuffer & indexBuffer)272     void setupRegularIndexedBuffer(GLBuffer &indexBuffer)
273     {
274         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
275         glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * mRegularIndices.size(),
276                      mRegularIndices.data(), GL_STATIC_DRAW);
277 
278         ASSERT_GL_NO_ERROR();
279     }
280 
setupPositionVertexAttribPointer()281     void setupPositionVertexAttribPointer()
282     {
283         glEnableVertexAttribArray(mPositionLoc);
284         glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
285     }
286 
setupInstanceIDVertexAttribPointer(GLuint instanceIDLoc)287     void setupInstanceIDVertexAttribPointer(GLuint instanceIDLoc)
288     {
289         glEnableVertexAttribArray(instanceIDLoc);
290         glVertexAttribPointer(instanceIDLoc, 1, GL_FLOAT, GL_FALSE, 0, 0);
291         glVertexAttribDivisor(instanceIDLoc, 1);
292     }
293 
doDrawArraysInstancedBaseInstance()294     void doDrawArraysInstancedBaseInstance()
295     {
296         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
297 
298         const uint32_t countPerDraw = kCountY * 6;
299 
300         for (uint32_t i = 0; i < kCountX; i += 2)
301         {
302             glDrawArraysInstancedBaseInstanceANGLE(GL_TRIANGLES, 0, countPerDraw, 2, i);
303         }
304     }
305 
doMultiDrawArraysInstancedBaseInstance()306     void doMultiDrawArraysInstancedBaseInstance()
307     {
308         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
309 
310         const uint32_t countPerDraw = kCountY * 6;
311 
312         const GLsizei drawCount = kCountX / 2;
313         const std::vector<GLsizei> counts(drawCount, countPerDraw);
314         const std::vector<GLsizei> firsts(drawCount, 0);
315         const std::vector<GLsizei> instanceCounts(drawCount, 2);
316         std::vector<GLuint> baseInstances(drawCount);
317         for (size_t i = 0; i < drawCount; i++)
318         {
319             baseInstances[i] = i * 2;
320         }
321         glMultiDrawArraysInstancedBaseInstanceANGLE(GL_TRIANGLES, firsts.data(), counts.data(),
322                                                     instanceCounts.data(), baseInstances.data(),
323                                                     drawCount);
324     }
325 
doDrawElementsInstancedBaseVertexBaseInstance()326     void doDrawElementsInstancedBaseVertexBaseInstance()
327     {
328         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
329 
330         const uint32_t countPerDraw = 6;
331 
332         for (uint32_t v = 0; v < kCountY; v++)
333         {
334             for (uint32_t i = 0; i < kCountX; i += 2)
335             {
336                 glDrawElementsInstancedBaseVertexBaseInstanceANGLE(
337                     GL_TRIANGLES, countPerDraw, GL_UNSIGNED_SHORT,
338                     reinterpret_cast<GLvoid *>(static_cast<uintptr_t>(0)), 2, v * 4, i);
339             }
340         }
341     }
342 
343     // Call this after the *BaseVertexBaseInstance draw call to check if value of BaseVertex and
344     // BaseInstance are reset to zero
doDrawArraysBaseInstanceReset()345     void doDrawArraysBaseInstanceReset()
346     {
347         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
348         glDrawArrays(GL_TRIANGLES, 0, 6 * kCountY);
349     }
350 
doDrawElementsBaseVertexBaseInstanceReset()351     void doDrawElementsBaseVertexBaseInstanceReset()
352     {
353         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
354         glDrawElements(GL_TRIANGLES, 6 * kCountY, GL_UNSIGNED_SHORT,
355                        reinterpret_cast<GLvoid *>(static_cast<uintptr_t>(0)));
356     }
357 
doMultiDrawElementsInstancedBaseVertexBaseInstance()358     void doMultiDrawElementsInstancedBaseVertexBaseInstance()
359     {
360         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
361 
362         const GLsizei drawCount = kCountX * kCountY / 2;
363         const std::vector<GLsizei> counts(drawCount, 6);
364         const std::vector<GLsizei> instanceCounts(drawCount, 2);
365         const std::vector<GLvoid *> indices(drawCount, 0);
366         std::vector<GLint> baseVertices(drawCount);
367         std::vector<GLuint> baseInstances(drawCount);
368 
369         GLsizei b = 0;
370         for (uint32_t v = 0; v < kCountY; v++)
371         {
372             for (uint32_t i = 0; i < kCountX; i += 2)
373             {
374                 baseVertices[b]  = v * 4;
375                 baseInstances[b] = i;
376                 b++;
377             }
378         }
379 
380         glMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE(
381             GL_TRIANGLES, counts.data(), GL_UNSIGNED_SHORT, indices.data(), instanceCounts.data(),
382             baseVertices.data(), baseInstances.data(), drawCount);
383     }
384 
checkDrawResult(bool hasBaseVertex,bool oneColumn=false)385     void checkDrawResult(bool hasBaseVertex, bool oneColumn = false)
386     {
387         uint32_t numColums = oneColumn ? 1 : kCountX;
388         for (uint32_t y = 0; y < kCountY; ++y)
389         {
390             for (uint32_t x = 0; x < numColums; ++x)
391             {
392                 uint32_t center_x = x * kTilePixelSize[0] + kTilePixelSize[0] / 2;
393                 uint32_t center_y = y * kTilePixelSize[1] + kTilePixelSize[1] / 2;
394 
395                 EXPECT_PIXEL_NEAR(center_x - kPixelCheckSize[0] / 2,
396                                   center_y - kPixelCheckSize[1] / 2,
397                                   256.0 * (1.0 - (float)x / (float)kCountX),
398                                   256.0 * (1.0 - (float)y / (float)kCountY),
399                                   useBaseVertexBuiltin() && hasBaseVertex && !oneColumn
400                                       ? 256.0 * (1.0 - (float)y / (float)kCountY)
401                                       : 255,
402                                   255, 3);
403             }
404         }
405     }
406 
TearDown()407     void TearDown() override { ANGLETestBase::ANGLETestTearDown(); }
408 
requestDrawBaseVertexBaseInstanceExtension()409     bool requestDrawBaseVertexBaseInstanceExtension()
410     {
411         if (IsGLExtensionRequestable("GL_ANGLE_base_vertex_base_instance"))
412         {
413             glRequestExtensionANGLE("GL_ANGLE_base_vertex_base_instance");
414         }
415 
416         if (!IsGLExtensionEnabled("GL_ANGLE_base_vertex_base_instance"))
417         {
418             return false;
419         }
420 
421         return true;
422     }
423 
requestInstancedExtension()424     bool requestInstancedExtension()
425     {
426         if (IsGLExtensionRequestable("GL_ANGLE_instanced_arrays"))
427         {
428             glRequestExtensionANGLE("GL_ANGLE_instanced_arrays");
429         }
430 
431         if (!IsGLExtensionEnabled("GL_ANGLE_instanced_arrays"))
432         {
433             return false;
434         }
435 
436         return true;
437     }
438 
requestExtensions()439     bool requestExtensions()
440     {
441         if (getClientMajorVersion() <= 2)
442         {
443             if (!requestInstancedExtension())
444             {
445                 return false;
446             }
447         }
448         return requestDrawBaseVertexBaseInstanceExtension();
449     }
450 
451     // Used for base vertex base instance draw calls
452     std::vector<GLushort> mIndices;
453     std::vector<GLfloat> mVertices;
454     std::vector<GLfloat> mNonIndexedVertices;
455     // Used when gl_BaseInstance is not used
456     std::array<GLfloat, kCountX> mInstancedArrayId;
457     std::array<GLfloat, kCountX> mInstancedArrayColorId;
458     // Used for regular draw calls without base vertex base instance
459     std::vector<GLushort> mRegularIndices;
460     GLint mPositionLoc;
461     GLuint mInstanceIDLoc;
462     GLuint mInstanceColorIDLoc;
463 };
464 
465 // Tests that compile a program with the extension succeeds
TEST_P(DrawBaseVertexBaseInstanceTest,CanCompile)466 TEST_P(DrawBaseVertexBaseInstanceTest, CanCompile)
467 {
468     ANGLE_SKIP_TEST_IF(!requestExtensions());
469     GLProgram p0;
470     setupProgram(p0, true, false);
471     GLProgram p1;
472     setupProgram(p1, true, true);
473     GLProgram p2;
474     setupProgram(p2, false, false);
475     GLProgram p3;
476     setupProgram(p3, false, true);
477 }
478 
479 // Tests if baseInstance works properly with instanced array with non-zero divisor
TEST_P(DrawBaseVertexBaseInstanceTest,BaseInstanceDivisor)480 TEST_P(DrawBaseVertexBaseInstanceTest, BaseInstanceDivisor)
481 {
482     ANGLE_SKIP_TEST_IF(!requestExtensions());
483     ANGLE_SKIP_TEST_IF(useBaseInstanceBuiltin());
484 
485     GLProgram program;
486     setupProgram(program, true, false, true);
487 
488     GLBuffer nonIndexedVertexBuffer;
489     setupNonIndexedBuffers(nonIndexedVertexBuffer);
490     setupPositionVertexAttribPointer();
491 
492     GLBuffer instanceIDBuffer;
493     GLBuffer instanceColorIDBuffer;
494 
495     setupInstanceIDBuffer(instanceIDBuffer);
496     setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
497     setupInstanceColorIDBuffer(instanceColorIDBuffer);
498     setupInstanceIDVertexAttribPointer(mInstanceColorIDLoc);
499 
500     doDrawArraysInstancedBaseInstance();
501     EXPECT_GL_NO_ERROR();
502     checkDrawResult(false);
503 
504     doDrawArraysBaseInstanceReset();
505     EXPECT_GL_NO_ERROR();
506     checkDrawResult(false, true);
507 
508     GLProgram programIndexed;
509     setupProgram(programIndexed, false, false, true);
510 
511     GLBuffer indexBuffer;
512     GLBuffer vertexBuffer;
513     setupIndexedBuffers(vertexBuffer, indexBuffer);
514     setupPositionVertexAttribPointer();
515 
516     glBindBuffer(GL_ARRAY_BUFFER, instanceIDBuffer);
517     setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
518     glBindBuffer(GL_ARRAY_BUFFER, instanceColorIDBuffer);
519     setupInstanceIDVertexAttribPointer(mInstanceColorIDLoc);
520 
521     doDrawElementsInstancedBaseVertexBaseInstance();
522     EXPECT_GL_NO_ERROR();
523     checkDrawResult(true);
524 
525     setupRegularIndexedBuffer(indexBuffer);
526     doDrawElementsBaseVertexBaseInstanceReset();
527     EXPECT_GL_NO_ERROR();
528     checkDrawResult(false, true);
529 }
530 
531 // Tests basic functionality of glDrawArraysInstancedBaseInstance
TEST_P(DrawBaseVertexBaseInstanceTest,DrawArraysInstancedBaseInstance)532 TEST_P(DrawBaseVertexBaseInstanceTest, DrawArraysInstancedBaseInstance)
533 {
534     // TODO(shrekshao): Temporarily skip this test
535     // before we could try updating win AMD bot driver version
536     // after Lab team fixed issues with ssh into bot machines
537     // Currently this test fail on certain Win7/Win2008Server AMD GPU
538     // with driver version 23.20.185.235 when using OpenGL backend.
539     // This failure couldn't be produced on local Win10 AMD machine with latest driver installed
540     // Same for the MultiDrawArraysInstancedBaseInstance test
541     if (IsAMD() && IsWindows() && IsDesktopOpenGL())
542     {
543         SystemInfo *systemInfo = GetTestSystemInfo();
544         if (!systemInfo->gpus.empty())
545         {
546             ANGLE_SKIP_TEST_IF(0x6613 == systemInfo->gpus[systemInfo->activeGPUIndex].deviceId);
547         }
548     }
549 
550     ANGLE_SKIP_TEST_IF(!requestExtensions());
551 
552     GLProgram program;
553     setupProgram(program, true);
554 
555     GLBuffer vertexBuffer;
556     setupNonIndexedBuffers(vertexBuffer);
557     setupPositionVertexAttribPointer();
558 
559     GLBuffer instanceIDBuffer;
560     if (!useBaseInstanceBuiltin())
561     {
562         setupInstanceIDBuffer(instanceIDBuffer);
563         setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
564     }
565 
566     doDrawArraysInstancedBaseInstance();
567     EXPECT_GL_NO_ERROR();
568     checkDrawResult(false);
569 
570     doDrawArraysBaseInstanceReset();
571     checkDrawResult(false, true);
572 }
573 
574 // Tests basic functionality of glMultiDrawArraysInstancedBaseInstance
TEST_P(DrawBaseVertexBaseInstanceTest,MultiDrawArraysInstancedBaseInstance)575 TEST_P(DrawBaseVertexBaseInstanceTest, MultiDrawArraysInstancedBaseInstance)
576 {
577     if (IsAMD() && IsWindows() && IsDesktopOpenGL())
578     {
579         SystemInfo *systemInfo = GetTestSystemInfo();
580         if (!(systemInfo->activeGPUIndex < 0 || systemInfo->gpus.empty()))
581         {
582             ANGLE_SKIP_TEST_IF(0x6613 == systemInfo->gpus[systemInfo->activeGPUIndex].deviceId);
583         }
584     }
585 
586     ANGLE_SKIP_TEST_IF(!requestExtensions());
587 
588     GLProgram program;
589     setupProgram(program, true, true);
590 
591     GLBuffer vertexBuffer;
592     setupNonIndexedBuffers(vertexBuffer);
593     setupPositionVertexAttribPointer();
594 
595     GLBuffer instanceIDBuffer;
596     if (!useBaseInstanceBuiltin())
597     {
598         setupInstanceIDBuffer(instanceIDBuffer);
599         setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
600     }
601 
602     doMultiDrawArraysInstancedBaseInstance();
603     EXPECT_GL_NO_ERROR();
604     checkDrawResult(false);
605 
606     doDrawArraysBaseInstanceReset();
607     checkDrawResult(false, true);
608 }
609 
610 // Tests basic functionality of glDrawElementsInstancedBaseVertexBaseInstance
TEST_P(DrawBaseVertexBaseInstanceTest,DrawElementsInstancedBaseVertexBaseInstance)611 TEST_P(DrawBaseVertexBaseInstanceTest, DrawElementsInstancedBaseVertexBaseInstance)
612 {
613     ANGLE_SKIP_TEST_IF(!requestExtensions());
614 
615     GLProgram program;
616     setupProgram(program, false);
617 
618     GLBuffer indexBuffer;
619     GLBuffer vertexBuffer;
620     setupIndexedBuffers(vertexBuffer, indexBuffer);
621     setupPositionVertexAttribPointer();
622 
623     GLBuffer instanceIDBuffer;
624     if (!useBaseInstanceBuiltin())
625     {
626         setupInstanceIDBuffer(instanceIDBuffer);
627         setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
628     }
629 
630     doDrawElementsInstancedBaseVertexBaseInstance();
631     EXPECT_GL_NO_ERROR();
632     checkDrawResult(true);
633 
634     setupRegularIndexedBuffer(indexBuffer);
635     doDrawElementsBaseVertexBaseInstanceReset();
636     EXPECT_GL_NO_ERROR();
637     checkDrawResult(true, true);
638 }
639 
640 // Tests basic functionality of glMultiDrawElementsInstancedBaseVertexBaseInstance
TEST_P(DrawBaseVertexBaseInstanceTest,MultiDrawElementsInstancedBaseVertexBaseInstance)641 TEST_P(DrawBaseVertexBaseInstanceTest, MultiDrawElementsInstancedBaseVertexBaseInstance)
642 {
643     ANGLE_SKIP_TEST_IF(!requestExtensions());
644 
645     GLProgram program;
646     setupProgram(program, false, true);
647 
648     GLBuffer indexBuffer;
649     GLBuffer vertexBuffer;
650     setupIndexedBuffers(vertexBuffer, indexBuffer);
651     setupPositionVertexAttribPointer();
652 
653     GLBuffer instanceIDBuffer;
654     if (!useBaseInstanceBuiltin())
655     {
656         setupInstanceIDBuffer(instanceIDBuffer);
657         setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
658     }
659 
660     doMultiDrawElementsInstancedBaseVertexBaseInstance();
661     EXPECT_GL_NO_ERROR();
662     checkDrawResult(true);
663 
664     setupRegularIndexedBuffer(indexBuffer);
665     doDrawElementsBaseVertexBaseInstanceReset();
666     EXPECT_GL_NO_ERROR();
667     checkDrawResult(true, true);
668 }
669 
670 const angle::PlatformParameters platforms[] = {
671     ES3_D3D11(),
672     ES3_OPENGL(),
673     ES3_OPENGLES(),
674     ES3_VULKAN(),
675 };
676 
677 INSTANTIATE_TEST_SUITE_P(
678     ,
679     DrawBaseVertexBaseInstanceTest,
680     testing::Combine(
681         testing::ValuesIn(::angle::FilterTestParams(platforms, ArraySize(platforms))),
682         testing::Values(BaseVertexOption::NoBaseVertex, BaseVertexOption::UseBaseVertex),
683         testing::Values(BaseInstanceOption::NoBaseInstance, BaseInstanceOption::UseBaseInstance)),
684     PrintToStringParamName());
685 
686 }  // namespace
687