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