• 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 ()__anon76d3c0330111::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_shader_builtin : 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         if (IsGLExtensionRequestable("GL_ANGLE_base_vertex_base_instance_shader_builtin"))
436         {
437             glRequestExtensionANGLE("GL_ANGLE_base_vertex_base_instance_shader_builtin");
438         }
439 
440         return true;
441     }
442 
requestInstancedExtension()443     bool requestInstancedExtension()
444     {
445         if (IsGLExtensionRequestable("GL_ANGLE_instanced_arrays"))
446         {
447             glRequestExtensionANGLE("GL_ANGLE_instanced_arrays");
448         }
449 
450         if (!IsGLExtensionEnabled("GL_ANGLE_instanced_arrays"))
451         {
452             return false;
453         }
454 
455         return true;
456     }
457 
requestExtensions()458     bool requestExtensions()
459     {
460         if (getClientMajorVersion() <= 2)
461         {
462             if (!requestInstancedExtension())
463             {
464                 return false;
465             }
466         }
467         return requestDrawBaseVertexBaseInstanceExtension();
468     }
469 
470     // Used for base vertex base instance draw calls
471     std::vector<GLushort> mIndices;
472     std::vector<GLfloat> mVertices;
473     std::vector<GLfloat> mNonIndexedVertices;
474     // Used when gl_BaseInstance is not used
475     std::array<GLfloat, kCountX> mInstancedArrayId;
476     std::array<GLfloat, kCountX> mInstancedArrayColorId;
477     // Used for regular draw calls without base vertex base instance
478     std::vector<GLushort> mRegularIndices;
479     GLint mPositionLoc;
480     GLuint mInstanceIDLoc;
481     GLuint mInstanceColorIDLoc;
482 };
483 
484 // Tests that compile a program with the extension succeeds
TEST_P(DrawBaseVertexBaseInstanceTest,CanCompile)485 TEST_P(DrawBaseVertexBaseInstanceTest, CanCompile)
486 {
487     ANGLE_SKIP_TEST_IF(!requestExtensions());
488     GLProgram p0;
489     setupProgram(p0, true, false);
490     GLProgram p1;
491     setupProgram(p1, true, true);
492     GLProgram p2;
493     setupProgram(p2, false, false);
494     GLProgram p3;
495     setupProgram(p3, false, true);
496 }
497 
498 // Tests if baseInstance works properly with instanced array with non-zero divisor
TEST_P(DrawBaseVertexBaseInstanceTest,BaseInstanceDivisor)499 TEST_P(DrawBaseVertexBaseInstanceTest, BaseInstanceDivisor)
500 {
501     ANGLE_SKIP_TEST_IF(!requestExtensions());
502     ANGLE_SKIP_TEST_IF(useBaseInstanceBuiltin());
503 
504     GLProgram program;
505     setupProgram(program, true, false, true);
506 
507     GLBuffer nonIndexedVertexBuffer;
508     setupNonIndexedBuffers(nonIndexedVertexBuffer);
509     setupPositionVertexAttribPointer();
510 
511     GLBuffer instanceIDBuffer;
512     GLBuffer instanceColorIDBuffer;
513 
514     setupInstanceIDBuffer(instanceIDBuffer);
515     setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
516     setupInstanceColorIDBuffer(instanceColorIDBuffer);
517     setupInstanceIDVertexAttribPointer(mInstanceColorIDLoc);
518 
519     doDrawArraysInstancedBaseInstance();
520     EXPECT_GL_NO_ERROR();
521     checkDrawResult(false);
522 
523     doDrawArraysBaseInstanceReset();
524     EXPECT_GL_NO_ERROR();
525     checkDrawResult(false, true);
526 
527     GLProgram programIndexed;
528     setupProgram(programIndexed, false, false, true);
529 
530     GLBuffer indexBuffer;
531     GLBuffer vertexBuffer;
532     setupIndexedBuffers(vertexBuffer, indexBuffer);
533     setupPositionVertexAttribPointer();
534 
535     glBindBuffer(GL_ARRAY_BUFFER, instanceIDBuffer);
536     setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
537     glBindBuffer(GL_ARRAY_BUFFER, instanceColorIDBuffer);
538     setupInstanceIDVertexAttribPointer(mInstanceColorIDLoc);
539 
540     doDrawElementsInstancedBaseVertexBaseInstance();
541     EXPECT_GL_NO_ERROR();
542     checkDrawResult(true);
543 
544     setupRegularIndexedBuffer(indexBuffer);
545     doDrawElementsBaseVertexBaseInstanceReset();
546     EXPECT_GL_NO_ERROR();
547     checkDrawResult(false, true);
548 }
549 
550 // Tests basic functionality of glDrawArraysInstancedBaseInstance
TEST_P(DrawBaseVertexBaseInstanceTest,DrawArraysInstancedBaseInstance)551 TEST_P(DrawBaseVertexBaseInstanceTest, DrawArraysInstancedBaseInstance)
552 {
553     // TODO(shrekshao): Temporarily skip this test
554     // before we could try updating win AMD bot driver version
555     // after Lab team fixed issues with ssh into bot machines
556     // Currently this test fail on certain Win7/Win2008Server AMD GPU
557     // with driver version 23.20.185.235 when using OpenGL backend.
558     // This failure couldn't be produced on local Win10 AMD machine with latest driver installed
559     // Same for the MultiDrawArraysInstancedBaseInstance test
560     if (IsAMD() && IsWindows() && IsDesktopOpenGL())
561     {
562         SystemInfo *systemInfo = GetTestSystemInfo();
563         if (!systemInfo->gpus.empty())
564         {
565             ANGLE_SKIP_TEST_IF(0x6613 == systemInfo->gpus[systemInfo->activeGPUIndex].deviceId);
566         }
567     }
568 
569     ANGLE_SKIP_TEST_IF(!requestExtensions());
570 
571     GLProgram program;
572     setupProgram(program, true);
573 
574     GLBuffer vertexBuffer;
575     setupNonIndexedBuffers(vertexBuffer);
576     setupPositionVertexAttribPointer();
577 
578     GLBuffer instanceIDBuffer;
579     if (!useBaseInstanceBuiltin())
580     {
581         setupInstanceIDBuffer(instanceIDBuffer);
582         setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
583     }
584 
585     doDrawArraysInstancedBaseInstance();
586     EXPECT_GL_NO_ERROR();
587     checkDrawResult(false);
588 
589     doDrawArraysBaseInstanceReset();
590     EXPECT_GL_NO_ERROR();
591     checkDrawResult(false, true);
592 }
593 
594 // Tests basic functionality of glMultiDrawArraysInstancedBaseInstance
TEST_P(DrawBaseVertexBaseInstanceTest,MultiDrawArraysInstancedBaseInstance)595 TEST_P(DrawBaseVertexBaseInstanceTest, MultiDrawArraysInstancedBaseInstance)
596 {
597     if (IsAMD() && IsWindows() && IsDesktopOpenGL())
598     {
599         SystemInfo *systemInfo = GetTestSystemInfo();
600         if (!(systemInfo->activeGPUIndex < 0 || systemInfo->gpus.empty()))
601         {
602             ANGLE_SKIP_TEST_IF(0x6613 == systemInfo->gpus[systemInfo->activeGPUIndex].deviceId);
603         }
604     }
605 
606     ANGLE_SKIP_TEST_IF(!requestExtensions());
607 
608     GLProgram program;
609     setupProgram(program, true, true);
610 
611     GLBuffer vertexBuffer;
612     setupNonIndexedBuffers(vertexBuffer);
613     setupPositionVertexAttribPointer();
614 
615     GLBuffer instanceIDBuffer;
616     if (!useBaseInstanceBuiltin())
617     {
618         setupInstanceIDBuffer(instanceIDBuffer);
619         setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
620     }
621 
622     doMultiDrawArraysInstancedBaseInstance();
623     EXPECT_GL_NO_ERROR();
624     checkDrawResult(false);
625 
626     doDrawArraysBaseInstanceReset();
627     EXPECT_GL_NO_ERROR();
628     checkDrawResult(false, true);
629 }
630 
631 // Tests basic functionality of glDrawElementsInstancedBaseVertexBaseInstance
TEST_P(DrawBaseVertexBaseInstanceTest,DrawElementsInstancedBaseVertexBaseInstance)632 TEST_P(DrawBaseVertexBaseInstanceTest, DrawElementsInstancedBaseVertexBaseInstance)
633 {
634     ANGLE_SKIP_TEST_IF(!requestExtensions());
635 
636     GLProgram program;
637     setupProgram(program, false);
638 
639     GLBuffer indexBuffer;
640     GLBuffer vertexBuffer;
641     setupIndexedBuffers(vertexBuffer, indexBuffer);
642     setupPositionVertexAttribPointer();
643 
644     GLBuffer instanceIDBuffer;
645     if (!useBaseInstanceBuiltin())
646     {
647         setupInstanceIDBuffer(instanceIDBuffer);
648         setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
649     }
650 
651     doDrawElementsInstancedBaseVertexBaseInstance();
652     EXPECT_GL_NO_ERROR();
653     checkDrawResult(true);
654 
655     setupRegularIndexedBuffer(indexBuffer);
656     doDrawElementsBaseVertexBaseInstanceReset();
657     EXPECT_GL_NO_ERROR();
658     checkDrawResult(true, true);
659 }
660 
661 // Tests basic functionality of glMultiDrawElementsInstancedBaseVertexBaseInstance
TEST_P(DrawBaseVertexBaseInstanceTest,MultiDrawElementsInstancedBaseVertexBaseInstance)662 TEST_P(DrawBaseVertexBaseInstanceTest, MultiDrawElementsInstancedBaseVertexBaseInstance)
663 {
664     ANGLE_SKIP_TEST_IF(!requestExtensions());
665 
666     GLProgram program;
667     setupProgram(program, false, true);
668 
669     GLBuffer indexBuffer;
670     GLBuffer vertexBuffer;
671     setupIndexedBuffers(vertexBuffer, indexBuffer);
672     setupPositionVertexAttribPointer();
673 
674     GLBuffer instanceIDBuffer;
675     if (!useBaseInstanceBuiltin())
676     {
677         setupInstanceIDBuffer(instanceIDBuffer);
678         setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
679     }
680 
681     doMultiDrawElementsInstancedBaseVertexBaseInstance();
682     EXPECT_GL_NO_ERROR();
683     checkDrawResult(true);
684 
685     setupRegularIndexedBuffer(indexBuffer);
686     doDrawElementsBaseVertexBaseInstanceReset();
687     EXPECT_GL_NO_ERROR();
688     checkDrawResult(true, true);
689 }
690 
691 const angle::PlatformParameters platforms[] = {
692     ES3_D3D11(),
693     ES3_OPENGL(),
694     ES3_OPENGLES(),
695     ES3_VULKAN(),
696 };
697 
698 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrawBaseVertexBaseInstanceTest);
699 INSTANTIATE_TEST_SUITE_P(
700     ,
701     DrawBaseVertexBaseInstanceTest,
702     testing::Combine(
703         testing::ValuesIn(::angle::FilterTestParams(platforms, ArraySize(platforms))),
704         testing::Values(BaseVertexOption::NoBaseVertex, BaseVertexOption::UseBaseVertex),
705         testing::Values(BaseInstanceOption::NoBaseInstance, BaseInstanceOption::UseBaseInstance),
706         testing::Values(BufferDataUsageOption::StaticDraw, BufferDataUsageOption::DynamicDraw)),
707     PrintToStringParamName());
708 
709 }  // namespace
710