• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2018 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 // MultiDrawTest: Tests of GL_ANGLE_multi_draw
8 // MultiDrawIndirectTest: Tests of GL_EXT_multi_draw_indirect
9 
10 #include "test_utils/ANGLETest.h"
11 #include "test_utils/gl_raii.h"
12 
13 using namespace angle;
14 
15 namespace
16 {
17 
18 // Create a kWidth * kHeight canvas equally split into kCountX * kCountY tiles
19 // each containing a quad partially covering each tile
20 constexpr uint32_t kWidth                  = 256;
21 constexpr uint32_t kHeight                 = 256;
22 constexpr uint32_t kCountX                 = 8;
23 constexpr uint32_t kCountY                 = 8;
24 constexpr uint32_t kQuadCount              = kCountX * kCountY;
25 constexpr uint32_t kTriCount               = kQuadCount * 2;
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 DrawIDOption
55 {
56     NoDrawID,
57     UseDrawID,
58 };
59 
60 enum class InstancingOption
61 {
62     NoInstancing,
63     UseInstancing,
64 };
65 
66 enum class BufferDataUsageOption
67 {
68     StaticDraw,
69     DynamicDraw
70 };
71 
72 using MultiDrawTestParams =
73     std::tuple<angle::PlatformParameters, DrawIDOption, InstancingOption, BufferDataUsageOption>;
74 
75 using MultiDrawIndirectTestParams = angle::PlatformParameters;
76 
77 struct PrintToStringParamName
78 {
operator ()__anon83b6334a0111::PrintToStringParamName79     std::string operator()(const ::testing::TestParamInfo<MultiDrawTestParams> &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) == InstancingOption::UseInstancing ? "__Instanced" : "")
86            << (std::get<1>(info.param) == DrawIDOption::UseDrawID ? "__DrawID" : "");
87         return ss.str();
88     }
89 };
90 
91 struct DrawArraysIndirectCommand
92 {
DrawArraysIndirectCommand__anon83b6334a0111::DrawArraysIndirectCommand93     DrawArraysIndirectCommand() : count(0u), instanceCount(0u), first(0u), baseInstance(0u) {}
DrawArraysIndirectCommand__anon83b6334a0111::DrawArraysIndirectCommand94     DrawArraysIndirectCommand(GLuint count, GLuint instanceCount, GLuint first, GLuint baseInstance)
95         : count(count), instanceCount(instanceCount), first(first), baseInstance(baseInstance)
96     {}
97     GLuint count;
98     GLuint instanceCount;
99     GLuint first;
100     GLuint baseInstance;
101 };
102 
103 struct DrawElementsIndirectCommand
104 {
DrawElementsIndirectCommand__anon83b6334a0111::DrawElementsIndirectCommand105     DrawElementsIndirectCommand()
106         : count(0), primCount(0), firstIndex(0), baseVertex(0), baseInstance(0)
107     {}
DrawElementsIndirectCommand__anon83b6334a0111::DrawElementsIndirectCommand108     DrawElementsIndirectCommand(GLuint count,
109                                 GLuint primCount,
110                                 GLuint firstIndex,
111                                 GLint baseVertex,
112                                 GLuint baseInstance)
113         : count(count),
114           primCount(primCount),
115           firstIndex(firstIndex),
116           baseVertex(baseVertex),
117           baseInstance(baseInstance)
118     {}
119     GLuint count;
120     GLuint primCount;
121     GLuint firstIndex;
122     GLint baseVertex;
123     GLuint baseInstance;
124 };
125 
126 // The tests in MultiDrawTest and MultiDrawNoInstancingSupportTest check the correctness
127 // of the ANGLE_multi_draw extension.
128 // An array of quads is drawn across the screen.
129 // gl_DrawID is checked by using it to select the color of the draw.
130 // MultiDraw*Instanced entrypoints use the existing instancing APIs which are
131 // more fully tested in InstancingTest.cpp.
132 // Correct interaction with the instancing APIs is tested here by using scaling
133 // and then instancing the array of quads over four quadrants on the screen.
134 class MultiDrawTest : public ANGLETestBase, public ::testing::TestWithParam<MultiDrawTestParams>
135 {
136   protected:
MultiDrawTest()137     MultiDrawTest()
138         : ANGLETestBase(std::get<0>(GetParam())),
139           mNonIndexedVertexBuffer(0u),
140           mVertexBuffer(0u),
141           mIndexBuffer(0u),
142           mInstanceBuffer(0u),
143           mProgram(0u),
144           mPositionLoc(0u),
145           mInstanceLoc(0u)
146     {
147         setWindowWidth(kWidth);
148         setWindowHeight(kHeight);
149         setConfigRedBits(8);
150         setConfigGreenBits(8);
151         setConfigBlueBits(8);
152         setConfigAlphaBits(8);
153     }
154 
SetUp()155     void SetUp() override { ANGLETestBase::ANGLETestSetUp(); }
156 
IsDrawIDTest() const157     bool IsDrawIDTest() const { return std::get<1>(GetParam()) == DrawIDOption::UseDrawID; }
158 
IsInstancedTest() const159     bool IsInstancedTest() const
160     {
161         return std::get<2>(GetParam()) == InstancingOption::UseInstancing;
162     }
163 
getBufferDataUsage() const164     GLenum getBufferDataUsage() const
165     {
166         return std::get<3>(GetParam()) == BufferDataUsageOption::StaticDraw ? GL_STATIC_DRAW
167                                                                             : GL_DYNAMIC_DRAW;
168     }
169 
VertexShaderSource()170     std::string VertexShaderSource()
171     {
172 
173         std::stringstream shader;
174         shader << (IsDrawIDTest() ? "#extension GL_ANGLE_multi_draw : require\n" : "")
175                << (IsInstancedTest() ? "attribute float vInstance;" : "") << R"(
176 attribute vec2 vPosition;
177 varying vec4 color;
178 void main()
179 {
180     int id = )" << (IsDrawIDTest() ? "gl_DrawID" : "0")
181                << ";"
182                << R"(
183     float quad_id = float(id / 2);
184     float color_id = quad_id - (3.0 * floor(quad_id / 3.0));
185     if (color_id == 0.0) {
186       color = vec4(1, 0, 0, 1);
187     } else if (color_id == 1.0) {
188       color = vec4(0, 1, 0, 1);
189     } else {
190       color = vec4(0, 0, 1, 1);
191     }
192 
193     mat3 transform = mat3(1.0);
194 )"
195                << (IsInstancedTest() ? R"(
196     transform[0][0] = 0.5;
197     transform[1][1] = 0.5;
198     if (vInstance == 0.0) {
199 
200     } else if (vInstance == 1.0) {
201         transform[2][0] = 0.5;
202     } else if (vInstance == 2.0) {
203         transform[2][1] = 0.5;
204     } else if (vInstance == 3.0) {
205         transform[2][0] = 0.5;
206         transform[2][1] = 0.5;
207     }
208 )"
209                                      : "")
210                << R"(
211     gl_Position = vec4(transform * vec3(vPosition, 1.0) * 2.0 - 1.0, 1);
212 })";
213 
214         return shader.str();
215     }
216 
FragmentShaderSource()217     std::string FragmentShaderSource()
218     {
219         return
220             R"(precision mediump float;
221             varying vec4 color;
222             void main()
223             {
224                 gl_FragColor = color;
225             })";
226     }
227 
SetupProgram()228     void SetupProgram()
229     {
230         mProgram = CompileProgram(VertexShaderSource().c_str(), FragmentShaderSource().c_str());
231         EXPECT_GL_NO_ERROR();
232         ASSERT_GE(mProgram, 1u);
233         glUseProgram(mProgram);
234         mPositionLoc = glGetAttribLocation(mProgram, "vPosition");
235         mInstanceLoc = glGetAttribLocation(mProgram, "vInstance");
236     }
237 
SetupBuffers()238     void SetupBuffers()
239     {
240         for (uint32_t y = 0; y < kCountY; ++y)
241         {
242             for (uint32_t x = 0; x < kCountX; ++x)
243             {
244                 // v3 ---- v2
245                 // |       |
246                 // |       |
247                 // v0 ---- v1
248                 uint32_t quadIndex         = y * kCountX + x;
249                 GLushort starting_index    = static_cast<GLushort>(4 * quadIndex);
250                 std::array<GLushort, 6> is = {0, 1, 2, 0, 2, 3};
251                 const auto vs              = getQuadVertices(x, y);
252                 for (GLushort i : is)
253                 {
254                     mIndices.push_back(starting_index + i);
255                 }
256 
257                 for (const auto &v : vs)
258                 {
259                     mVertices.insert(mVertices.end(), v.begin(), v.end());
260                 }
261 
262                 for (GLushort i : is)
263                 {
264                     mNonIndexedVertices.insert(mNonIndexedVertices.end(), vs[i].begin(),
265                                                vs[i].end());
266                 }
267             }
268         }
269 
270         std::array<GLfloat, 4> instances{0, 1, 2, 3};
271 
272         glGenBuffers(1, &mNonIndexedVertexBuffer);
273         glBindBuffer(GL_ARRAY_BUFFER, mNonIndexedVertexBuffer);
274         glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mNonIndexedVertices.size(),
275                      mNonIndexedVertices.data(), getBufferDataUsage());
276 
277         glGenBuffers(1, &mVertexBuffer);
278         glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
279         glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mVertices.size(), mVertices.data(),
280                      getBufferDataUsage());
281 
282         glGenBuffers(1, &mIndexBuffer);
283         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
284         glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * mIndices.size(), mIndices.data(),
285                      getBufferDataUsage());
286 
287         glGenBuffers(1, &mInstanceBuffer);
288         glBindBuffer(GL_ARRAY_BUFFER, mInstanceBuffer);
289         glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * instances.size(), instances.data(),
290                      getBufferDataUsage());
291 
292         ASSERT_GL_NO_ERROR();
293     }
294 
DoVertexAttribDivisor(GLint location,GLuint divisor)295     void DoVertexAttribDivisor(GLint location, GLuint divisor)
296     {
297         if (getClientMajorVersion() <= 2)
298         {
299             ASSERT_TRUE(IsGLExtensionEnabled("GL_ANGLE_instanced_arrays"));
300             glVertexAttribDivisorANGLE(location, divisor);
301         }
302         else
303         {
304             glVertexAttribDivisor(location, divisor);
305         }
306     }
307 
DoDrawArrays()308     void DoDrawArrays()
309     {
310         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
311         glBindBuffer(GL_ARRAY_BUFFER, mNonIndexedVertexBuffer);
312         glEnableVertexAttribArray(mPositionLoc);
313         glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
314 
315         std::vector<GLint> firsts(kTriCount);
316         std::vector<GLsizei> counts(kTriCount, 3);
317         for (uint32_t i = 0; i < kTriCount; ++i)
318             firsts[i] = i * 3;
319 
320         if (IsInstancedTest())
321         {
322             glBindBuffer(GL_ARRAY_BUFFER, mInstanceBuffer);
323             glEnableVertexAttribArray(mInstanceLoc);
324             glVertexAttribPointer(mInstanceLoc, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
325             DoVertexAttribDivisor(mInstanceLoc, 1);
326             std::vector<GLsizei> instanceCounts(kTriCount, 4);
327             glMultiDrawArraysInstancedANGLE(GL_TRIANGLES, firsts.data(), counts.data(),
328                                             instanceCounts.data(), kTriCount);
329         }
330         else
331         {
332             glMultiDrawArraysANGLE(GL_TRIANGLES, firsts.data(), counts.data(), kTriCount);
333         }
334     }
335 
DoDrawElements()336     void DoDrawElements()
337     {
338         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
339         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
340         glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
341         glEnableVertexAttribArray(mPositionLoc);
342         glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
343 
344         std::vector<GLsizei> counts(kTriCount, 3);
345         std::vector<const GLvoid *> indices(kTriCount);
346         for (uint32_t i = 0; i < kTriCount; ++i)
347             indices[i] = reinterpret_cast<GLvoid *>(static_cast<uintptr_t>(i * 3 * 2));
348 
349         if (IsInstancedTest())
350         {
351             glBindBuffer(GL_ARRAY_BUFFER, mInstanceBuffer);
352             glEnableVertexAttribArray(mInstanceLoc);
353             glVertexAttribPointer(mInstanceLoc, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
354             DoVertexAttribDivisor(mInstanceLoc, 1);
355             std::vector<GLsizei> instanceCounts(kTriCount, 4);
356             glMultiDrawElementsInstancedANGLE(GL_TRIANGLES, counts.data(), GL_UNSIGNED_SHORT,
357                                               indices.data(), instanceCounts.data(), kTriCount);
358         }
359         else
360         {
361             glMultiDrawElementsANGLE(GL_TRIANGLES, counts.data(), GL_UNSIGNED_SHORT, indices.data(),
362                                      kTriCount);
363         }
364     }
365 
CheckDrawResult()366     void CheckDrawResult()
367     {
368         for (uint32_t y = 0; y < kCountY; ++y)
369         {
370             for (uint32_t x = 0; x < kCountX; ++x)
371             {
372                 uint32_t center_x             = x * kTilePixelSize[0] + kTilePixelSize[0] / 2;
373                 uint32_t center_y             = y * kTilePixelSize[1] + kTilePixelSize[1] / 2;
374                 uint32_t quadID               = IsDrawIDTest() ? y * kCountX + x : 0;
375                 uint32_t colorID              = quadID % 3u;
376                 std::array<GLColor, 3> colors = {GLColor(255, 0, 0, 255), GLColor(0, 255, 0, 255),
377                                                  GLColor(0, 0, 255, 255)};
378                 GLColor expected              = colors[colorID];
379 
380                 if (IsInstancedTest())
381                 {
382                     EXPECT_PIXEL_RECT_EQ(center_x / 2 - kPixelCheckSize[0] / 4,
383                                          center_y / 2 - kPixelCheckSize[1] / 4,
384                                          kPixelCheckSize[0] / 2, kPixelCheckSize[1] / 2, expected);
385                     EXPECT_PIXEL_RECT_EQ(center_x / 2 - kPixelCheckSize[0] / 4 + kWidth / 2,
386                                          center_y / 2 - kPixelCheckSize[1] / 4,
387                                          kPixelCheckSize[0] / 2, kPixelCheckSize[1] / 2, expected);
388                     EXPECT_PIXEL_RECT_EQ(center_x / 2 - kPixelCheckSize[0] / 4,
389                                          center_y / 2 - kPixelCheckSize[1] / 4 + kHeight / 2,
390                                          kPixelCheckSize[0] / 2, kPixelCheckSize[1] / 2, expected);
391                     EXPECT_PIXEL_RECT_EQ(center_x / 2 - kPixelCheckSize[0] / 4 + kWidth / 2,
392                                          center_y / 2 - kPixelCheckSize[1] / 4 + kHeight / 2,
393                                          kPixelCheckSize[0] / 2, kPixelCheckSize[1] / 2, expected);
394                 }
395                 else
396                 {
397                     EXPECT_PIXEL_RECT_EQ(center_x - kPixelCheckSize[0] / 2,
398                                          center_y - kPixelCheckSize[1] / 2, kPixelCheckSize[0],
399                                          kPixelCheckSize[1], expected);
400                 }
401             }
402         }
403     }
404 
TearDown()405     void TearDown() override
406     {
407         if (mNonIndexedVertexBuffer != 0u)
408         {
409             glDeleteBuffers(1, &mNonIndexedVertexBuffer);
410         }
411         if (mVertexBuffer != 0u)
412         {
413             glDeleteBuffers(1, &mVertexBuffer);
414         }
415         if (mIndexBuffer != 0u)
416         {
417             glDeleteBuffers(1, &mIndexBuffer);
418         }
419         if (mInstanceBuffer != 0u)
420         {
421             glDeleteBuffers(1, &mInstanceBuffer);
422         }
423         if (mProgram != 0)
424         {
425             glDeleteProgram(mProgram);
426         }
427         ANGLETestBase::ANGLETestTearDown();
428     }
429 
requestMultiDrawExtension()430     bool requestMultiDrawExtension() { return EnsureGLExtensionEnabled("GL_ANGLE_multi_draw"); }
431 
requestInstancedExtension()432     bool requestInstancedExtension()
433     {
434         return EnsureGLExtensionEnabled("GL_ANGLE_instanced_arrays");
435     }
436 
requestExtensions()437     bool requestExtensions()
438     {
439         if (IsInstancedTest() && getClientMajorVersion() <= 2)
440         {
441             if (!requestInstancedExtension())
442             {
443                 return false;
444             }
445         }
446         return requestMultiDrawExtension();
447     }
448 
449     std::vector<GLushort> mIndices;
450     std::vector<GLfloat> mVertices;
451     std::vector<GLfloat> mNonIndexedVertices;
452     GLuint mNonIndexedVertexBuffer;
453     GLuint mVertexBuffer;
454     GLuint mIndexBuffer;
455     GLuint mInstanceBuffer;
456     GLuint mProgram;
457     GLint mPositionLoc;
458     GLint mInstanceLoc;
459 };
460 
461 class MultiDrawNoInstancingSupportTest : public MultiDrawTest
462 {
SetUp()463     void SetUp() override
464     {
465         ASSERT_LE(getClientMajorVersion(), 2);
466         ASSERT_TRUE(IsInstancedTest());
467         MultiDrawTest::SetUp();
468     }
469 };
470 
471 // The tests in MultiDrawIndirectTest check the correctness
472 // of the EXT_multi_draw_indirect extension.
473 // 4 magenta triangles are drawn at the corners of the screen
474 // in different orders from the same vertex and index arrays.
475 class MultiDrawIndirectTest : public ANGLETestBase,
476                               public ::testing::TestWithParam<MultiDrawIndirectTestParams>
477 {
478   protected:
MultiDrawIndirectTest()479     MultiDrawIndirectTest()
480         : ANGLETestBase(GetParam()),
481           mPositionLoc(0u),
482           mColorLoc(0u),
483           mVertexBuffer(0u),
484           mColorBuffer(0u),
485           mIndexBuffer(0u),
486           mIndirectBuffer(0u),
487           mProgram(0u)
488     {
489         setWindowWidth(kWidth);
490         setWindowHeight(kHeight);
491         setConfigRedBits(8);
492         setConfigGreenBits(8);
493         setConfigBlueBits(8);
494         setConfigAlphaBits(8);
495     }
496 
SetUp()497     void SetUp() override { ANGLETestBase::ANGLETestSetUp(); }
498 
SetupProgramIndirect(bool isMultiColor)499     void SetupProgramIndirect(bool isMultiColor)
500     {
501         // Define the vertex and fragment shaders
502         std::stringstream kVS;
503         kVS << R"(#version 310 es
504 in vec3 aPos;
505 )"
506             << (isMultiColor ? R"(in vec4 aColor;
507 out vec4 vColor;)"
508                              : "")
509             << R"(
510 void main()
511 {
512     gl_Position = vec4(aPos.x, aPos.y, 0, 1);
513 )" << (isMultiColor ? R"(vColor = vec4(aColor.x, aColor.y, aColor.z, 1.0);)" : "")
514             << R"(
515 })";
516 
517         std::stringstream kFS;
518         kFS << R"(#version 310 es
519 precision mediump float;
520 )"
521             << (isMultiColor ? R"(in vec4 vColor;
522 )"
523                              : "")
524             << R"(
525 out vec4 colorOut;
526 void main()
527 {
528 )" << (isMultiColor ? R"(colorOut = vColor;)" : R"(colorOut = vec4(1.0, 0.0, 1.0, 1.0);)")
529             << R"(
530 })";
531         mProgram = CompileProgram(kVS.str().c_str(), kFS.str().c_str());
532         EXPECT_GL_NO_ERROR();
533         ASSERT_GE(mProgram, 1u);
534         glUseProgram(mProgram);
535         mPositionLoc = glGetAttribLocation(mProgram, "aPos");
536         mColorLoc    = glGetAttribLocation(mProgram, "aColor");
537     }
538 
TearDown()539     void TearDown() override
540     {
541         if (mVertexBuffer != 0u)
542         {
543             glDeleteBuffers(1, &mVertexBuffer);
544         }
545         if (mColorBuffer != 0u)
546         {
547             glDeleteBuffers(1, &mColorBuffer);
548         }
549         if (mIndexBuffer != 0u)
550         {
551             glDeleteBuffers(1, &mIndexBuffer);
552         }
553         if (mProgram != 0)
554         {
555             glDeleteProgram(mProgram);
556         }
557         if (mIndirectBuffer != 0u)
558         {
559             glDeleteBuffers(1, &mIndirectBuffer);
560         }
561         ANGLETestBase::ANGLETestTearDown();
562     }
563 
564     GLint mPositionLoc;
565     GLint mColorLoc;
566     GLuint mVertexBuffer;
567     GLuint mColorBuffer;
568     GLuint mIndexBuffer;
569     GLuint mIndirectBuffer;
570     GLuint mProgram;
571 };
572 
573 // glMultiDraw*ANGLE are emulated and should always be available
TEST_P(MultiDrawTest,RequestExtension)574 TEST_P(MultiDrawTest, RequestExtension)
575 {
576     EXPECT_TRUE(requestMultiDrawExtension());
577 }
578 
579 // Test that compile a program with the extension succeeds
TEST_P(MultiDrawTest,CanCompile)580 TEST_P(MultiDrawTest, CanCompile)
581 {
582     ANGLE_SKIP_TEST_IF(!requestExtensions());
583     SetupProgram();
584 }
585 
586 // Tests basic functionality of glMultiDrawArraysANGLE
TEST_P(MultiDrawTest,MultiDrawArrays)587 TEST_P(MultiDrawTest, MultiDrawArrays)
588 {
589     ANGLE_SKIP_TEST_IF(!requestExtensions());
590 
591     // http://anglebug.com/5265
592     ANGLE_SKIP_TEST_IF(IsInstancedTest() && IsOSX() && IsIntelUHD630Mobile() && IsDesktopOpenGL());
593 
594     SetupBuffers();
595     SetupProgram();
596     DoDrawArrays();
597     EXPECT_GL_NO_ERROR();
598     CheckDrawResult();
599 }
600 
601 // Tests basic functionality of glMultiDrawElementsANGLE
TEST_P(MultiDrawTest,MultiDrawElements)602 TEST_P(MultiDrawTest, MultiDrawElements)
603 {
604     ANGLE_SKIP_TEST_IF(!requestExtensions());
605     SetupBuffers();
606     SetupProgram();
607     DoDrawElements();
608     EXPECT_GL_NO_ERROR();
609     CheckDrawResult();
610 }
611 
612 // Tests basic functionality of glMultiDrawArraysIndirectEXT
TEST_P(MultiDrawIndirectTest,MultiDrawArraysIndirect)613 TEST_P(MultiDrawIndirectTest, MultiDrawArraysIndirect)
614 {
615     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multi_draw_indirect"));
616 
617     // Set up the vertex array
618     const GLint triangleCount           = 4;
619     const std::vector<GLfloat> vertices = {
620         -1, 1,  0, -1, 0, 0, 0, 1,  0, 1, 1,  0, 1, 0,  0, 0, 1, 0,
621         -1, -1, 0, -1, 0, 0, 0, -1, 0, 1, -1, 0, 0, -1, 0, 1, 0, 0,
622     };
623 
624     // Set up the vertex buffer
625     GLVertexArray vao;
626     glBindVertexArray(vao);
627 
628     glGenBuffers(1, &mVertexBuffer);
629     glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
630     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * vertices.size(), vertices.data(),
631                  GL_STATIC_DRAW);
632     EXPECT_GL_NO_ERROR();
633 
634     // Generate program
635     SetupProgramIndirect(false);
636 
637     // Set up the vertex array format
638     glEnableVertexAttribArray(mPositionLoc);
639     glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
640     EXPECT_GL_NO_ERROR();
641 
642     // Set up the indirect data array
643     std::array<DrawArraysIndirectCommand, triangleCount> indirectData;
644     const GLsizei icSize = sizeof(DrawArraysIndirectCommand);
645     for (auto i = 0; i < triangleCount; i++)
646     {
647         indirectData[i] = DrawArraysIndirectCommand(3, 1, 3 * i, i);
648     }
649 
650     glGenBuffers(1, &mIndirectBuffer);
651     glBindBuffer(GL_DRAW_INDIRECT_BUFFER, mIndirectBuffer);
652     glBufferData(GL_DRAW_INDIRECT_BUFFER, icSize * indirectData.size(), indirectData.data(),
653                  GL_STATIC_DRAW);
654     EXPECT_GL_NO_ERROR();
655 
656     // Invalid value check for drawcount and stride
657     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
658     glMultiDrawArraysIndirectEXT(GL_TRIANGLES, nullptr, 0, 0);
659     EXPECT_GL_ERROR(GL_INVALID_VALUE);
660     glMultiDrawArraysIndirectEXT(GL_TRIANGLES, nullptr, -1, 0);
661     EXPECT_GL_ERROR(GL_INVALID_VALUE);
662     glMultiDrawArraysIndirectEXT(GL_TRIANGLES, nullptr, 1, 2);
663     EXPECT_GL_ERROR(GL_INVALID_VALUE);
664 
665     // Check the error from sourcing beyond the allocated buffer size
666     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
667     glMultiDrawArraysIndirectEXT(
668         GL_TRIANGLES,
669         reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize * triangleCount)), 1, 0);
670     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
671 
672     // Draw all triangles using glMultiDrawArraysIndirect
673     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
674     glMultiDrawArraysIndirectEXT(GL_TRIANGLES, nullptr, triangleCount, 0);
675     EXPECT_GL_NO_ERROR();
676 
677     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
678     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::magenta);
679     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::magenta);
680     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::magenta);
681     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
682 
683     // Draw the triangles in different order
684     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
685     glMultiDrawArraysIndirectEXT(GL_TRIANGLES, nullptr, 1, 0);
686     glMultiDrawArraysIndirectEXT(GL_TRIANGLES,
687                                  reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize * 2)),
688                                  triangleCount - 2, 0);
689     glMultiDrawArraysIndirectEXT(
690         GL_TRIANGLES, reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize)), 1, 0);
691     EXPECT_GL_NO_ERROR();
692 
693     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
694     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::magenta);
695     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::magenta);
696     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::magenta);
697     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
698 
699     // Draw the triangles partially using stride
700     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
701     glMultiDrawArraysIndirectEXT(GL_TRIANGLES, nullptr, 2, icSize * 3);
702     EXPECT_GL_NO_ERROR();
703 
704     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
705     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::magenta);
706     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::magenta);
707     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::transparentBlack);
708     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
709 }
710 
711 // Tests basic functionality of glMultiDrawElementsIndirectEXT
TEST_P(MultiDrawIndirectTest,MultiDrawElementsIndirect)712 TEST_P(MultiDrawIndirectTest, MultiDrawElementsIndirect)
713 {
714     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multi_draw_indirect"));
715 
716     // Set up the vertex array
717     const GLint triangleCount           = 4;
718     const std::vector<GLfloat> vertices = {
719         -1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, -1, 0, 0, -1, 0, -1, -1, 0, -1, 0, 0,
720     };
721     const std::vector<GLuint> indices = {
722         1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 0, 1,
723     };
724 
725     // Set up the vertex and index buffers
726     GLVertexArray vao;
727     glBindVertexArray(vao);
728 
729     glGenBuffers(1, &mVertexBuffer);
730     glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
731     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * vertices.size(), vertices.data(),
732                  GL_STATIC_DRAW);
733 
734     glGenBuffers(1, &mIndexBuffer);
735     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
736     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indices.size(), indices.data(),
737                  GL_STATIC_DRAW);
738     EXPECT_GL_NO_ERROR();
739 
740     // Generate program
741     SetupProgramIndirect(false);
742 
743     // Set up the vertex array format
744     glEnableVertexAttribArray(mPositionLoc);
745     glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
746     EXPECT_GL_NO_ERROR();
747 
748     // Set up the indirect data array
749     std::array<DrawElementsIndirectCommand, triangleCount> indirectData;
750     const GLsizei icSize = sizeof(DrawElementsIndirectCommand);
751     for (auto i = 0; i < triangleCount; i++)
752     {
753         indirectData[i] = DrawElementsIndirectCommand(3, 1, 3 * i, 0, i);
754     }
755 
756     glGenBuffers(1, &mIndirectBuffer);
757     glBindBuffer(GL_DRAW_INDIRECT_BUFFER, mIndirectBuffer);
758     glBufferData(GL_DRAW_INDIRECT_BUFFER, icSize * indirectData.size(), indirectData.data(),
759                  GL_STATIC_DRAW);
760     EXPECT_GL_NO_ERROR();
761 
762     // Invalid value check for drawcount and stride
763     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
764     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr, 0, 0);
765     EXPECT_GL_ERROR(GL_INVALID_VALUE);
766     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr, -1, 0);
767     EXPECT_GL_ERROR(GL_INVALID_VALUE);
768     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr, 1, 2);
769     EXPECT_GL_ERROR(GL_INVALID_VALUE);
770 
771     // Check the error from sourcing beyond the allocated buffer size
772     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
773     glMultiDrawElementsIndirectEXT(
774         GL_TRIANGLES, GL_UNSIGNED_INT,
775         reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize * triangleCount)), 1, 0);
776     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
777 
778     // Draw all triangles using glMultiDrawElementsIndirect
779     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
780     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr, triangleCount, 0);
781     EXPECT_GL_NO_ERROR();
782 
783     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
784     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::magenta);
785     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::magenta);
786     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::magenta);
787     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
788 
789     // Draw the triangles in a different order
790     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
791     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr, 1, 0);
792     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_INT,
793                                    reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize)),
794                                    triangleCount - 2, 0);
795     glMultiDrawElementsIndirectEXT(
796         GL_TRIANGLES, GL_UNSIGNED_INT,
797         reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize * 3)), 1, 0);
798     EXPECT_GL_NO_ERROR();
799 
800     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
801     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::magenta);
802     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::magenta);
803     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::magenta);
804     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
805 
806     // Draw the triangles partially using stride
807     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
808     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr, 2, icSize * 3);
809     EXPECT_GL_NO_ERROR();
810 
811     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
812     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::magenta);
813     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::transparentBlack);
814     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::magenta);
815     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
816 }
817 
818 // Tests functionality of glMultiDrawElementsIndirectEXT with more than one triangle in one element
819 // of the indirect buffer.
TEST_P(MultiDrawIndirectTest,MultiDrawElementsIndirectMultipleTriangles)820 TEST_P(MultiDrawIndirectTest, MultiDrawElementsIndirectMultipleTriangles)
821 {
822     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multi_draw_indirect"));
823 
824     // Set up the vertex array
825     const GLint triangleCount           = 4;
826     const std::vector<GLfloat> vertices = {
827         -1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, -1, 0, 0, -1, 0, -1, -1, 0, -1, 0, 0,
828     };
829     const std::vector<GLuint> indices = {
830         1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 0, 1,
831     };
832 
833     // Set up the vertex and index buffers
834     GLVertexArray vao;
835     glBindVertexArray(vao);
836 
837     glGenBuffers(1, &mVertexBuffer);
838     glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
839     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * vertices.size(), vertices.data(),
840                  GL_STATIC_DRAW);
841 
842     glGenBuffers(1, &mIndexBuffer);
843     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
844     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indices.size(), indices.data(),
845                  GL_STATIC_DRAW);
846     EXPECT_GL_NO_ERROR();
847 
848     // Generate program
849     SetupProgramIndirect(false);
850 
851     // Set up the vertex array format
852     glEnableVertexAttribArray(mPositionLoc);
853     glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
854     EXPECT_GL_NO_ERROR();
855 
856     // Set up the indirect data array; first element represents two triangles.
857     std::array<DrawElementsIndirectCommand, triangleCount - 1> indirectData;
858     const GLsizei icSize = sizeof(DrawElementsIndirectCommand);
859     for (auto i = 0; i < triangleCount - 1; i++)
860     {
861         if (i == 0)
862         {
863             indirectData[i] = DrawElementsIndirectCommand(6, 2, 0, 0, i);
864         }
865         else
866         {
867             indirectData[i] = DrawElementsIndirectCommand(3, 1, 3 * (i + 1), 0, i);
868         }
869     }
870 
871     glGenBuffers(1, &mIndirectBuffer);
872     glBindBuffer(GL_DRAW_INDIRECT_BUFFER, mIndirectBuffer);
873     glBufferData(GL_DRAW_INDIRECT_BUFFER, icSize * indirectData.size(), indirectData.data(),
874                  GL_STATIC_DRAW);
875     EXPECT_GL_NO_ERROR();
876 
877     // Draw all triangles using glMultiDrawElementsIndirect
878     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
879     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr, triangleCount - 1, 0);
880     EXPECT_GL_NO_ERROR();
881 
882     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
883     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::magenta);
884     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::magenta);
885     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::magenta);
886     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
887 }
888 
889 // Tests glMultiDrawElementsIndirectEXT with glMultiDrawElementsANGLE to see if the index buffer
890 // offset is being reset.
TEST_P(MultiDrawIndirectTest,MultiDrawElementsIndirectCheckBufferOffset)891 TEST_P(MultiDrawIndirectTest, MultiDrawElementsIndirectCheckBufferOffset)
892 {
893     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multi_draw_indirect"));
894 
895     // Set up the vertex array
896     const GLint triangleCount           = 4;
897     const std::vector<GLfloat> vertices = {
898         -1, 0, 0, -1, 1,  0, 0, 1,  0, 0, 1,  0, 1,  1,  0, 1,  0, 0,
899         1,  0, 0, 1,  -1, 0, 0, -1, 0, 0, -1, 0, -1, -1, 0, -1, 0, 0,
900     };
901     const std::vector<GLfloat> colors = {
902         1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0,
903         0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0,
904     };
905     const std::vector<GLuint> indices = {
906         3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2,
907     };
908 
909     // Set up the vertex and index buffers
910     GLVertexArray vao;
911     glBindVertexArray(vao);
912 
913     glGenBuffers(1, &mVertexBuffer);
914     glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
915     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * vertices.size(), vertices.data(),
916                  GL_STATIC_DRAW);
917 
918     glGenBuffers(1, &mColorBuffer);
919     glBindBuffer(GL_ARRAY_BUFFER, mColorBuffer);
920     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * colors.size(), colors.data(), GL_STATIC_DRAW);
921 
922     glGenBuffers(1, &mIndexBuffer);
923     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
924     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indices.size(), indices.data(),
925                  GL_STATIC_DRAW);
926     EXPECT_GL_NO_ERROR();
927 
928     // Generate program
929     SetupProgramIndirect(true);
930 
931     // Set up the vertex array format
932     glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
933     glEnableVertexAttribArray(mPositionLoc);
934     glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
935     EXPECT_GL_NO_ERROR();
936 
937     glBindBuffer(GL_ARRAY_BUFFER, mColorBuffer);
938     glEnableVertexAttribArray(mColorLoc);
939     glVertexAttribPointer(mColorLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
940     EXPECT_GL_NO_ERROR();
941 
942     // Set up the arrays for the direct draw
943     std::vector<GLsizei> counts(triangleCount, 3);
944     std::vector<const GLvoid *> indicesDirect(triangleCount);
945     for (auto i = 0; i < triangleCount; i++)
946     {
947         indicesDirect[i] =
948             reinterpret_cast<GLvoid *>(static_cast<uintptr_t>(i * 3 * sizeof(GLuint)));
949     }
950 
951     // Set up the indirect data array for indirect draw
952     std::array<DrawElementsIndirectCommand, triangleCount> indirectData;
953     const GLsizei icSize = sizeof(DrawElementsIndirectCommand);
954     for (auto i = 0; i < triangleCount; i++)
955     {
956         indirectData[i] = DrawElementsIndirectCommand(3, 1, 3 * i, 0, i);
957     }
958 
959     glGenBuffers(1, &mIndirectBuffer);
960     glBindBuffer(GL_DRAW_INDIRECT_BUFFER, mIndirectBuffer);
961     glBufferData(GL_DRAW_INDIRECT_BUFFER, icSize * indirectData.size(), indirectData.data(),
962                  GL_STATIC_DRAW);
963     EXPECT_GL_NO_ERROR();
964 
965     // Draw using glMultiDrawElementsIndirect
966     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
967     glMultiDrawElementsIndirectEXT(
968         GL_TRIANGLES, GL_UNSIGNED_INT,
969         reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize * 2)), triangleCount - 2, 0);
970     EXPECT_GL_NO_ERROR();
971 
972     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
973     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::red);
974     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::transparentBlack);
975     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::transparentBlack);
976     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
977 
978     // Draw using glMultiDrawElementsANGLE
979     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
980     glMultiDrawElementsANGLE(GL_TRIANGLES, counts.data(), GL_UNSIGNED_INT, indicesDirect.data(),
981                              triangleCount);
982     EXPECT_GL_NO_ERROR();
983 
984     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
985     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::red);
986     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::blue);
987     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::green);
988     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
989 
990     // Draw using glMultiDrawElementsANGLE again
991     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
992     glMultiDrawElementsANGLE(GL_TRIANGLES, counts.data(), GL_UNSIGNED_INT, indicesDirect.data(),
993                              triangleCount - 1);
994     EXPECT_GL_NO_ERROR();
995 
996     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
997     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::transparentBlack);
998     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::blue);
999     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::green);
1000     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
1001 
1002     // Draw using glMultiDrawElementsIndirect again
1003     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1004     glMultiDrawElementsIndirectEXT(
1005         GL_TRIANGLES, GL_UNSIGNED_INT,
1006         reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize * 3)), triangleCount - 3, 0);
1007     EXPECT_GL_NO_ERROR();
1008 
1009     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
1010     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::red);
1011     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::transparentBlack);
1012     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::transparentBlack);
1013     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
1014 
1015     // Draw using glMultiDrawElementsIndirect one more time
1016     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1017     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr, triangleCount, 0);
1018     EXPECT_GL_NO_ERROR();
1019 
1020     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
1021     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::red);
1022     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::blue);
1023     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::green);
1024     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
1025 }
1026 
1027 // Check that glMultiDraw*Instanced without instancing support results in GL_INVALID_OPERATION
TEST_P(MultiDrawNoInstancingSupportTest,InvalidOperation)1028 TEST_P(MultiDrawNoInstancingSupportTest, InvalidOperation)
1029 {
1030     ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_ANGLE_instanced_arrays"));
1031     requestMultiDrawExtension();
1032     SetupBuffers();
1033     SetupProgram();
1034 
1035     GLint first       = 0;
1036     GLsizei count     = 3;
1037     GLvoid *indices   = nullptr;
1038     GLsizei instances = 1;
1039 
1040     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1041     glBindBuffer(GL_ARRAY_BUFFER, mNonIndexedVertexBuffer);
1042     glEnableVertexAttribArray(mPositionLoc);
1043     glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1044     glMultiDrawArraysInstancedANGLE(GL_TRIANGLES, &first, &count, &instances, 1);
1045     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1046 
1047     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1048     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
1049     glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
1050     glEnableVertexAttribArray(mPositionLoc);
1051     glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1052     glMultiDrawElementsInstancedANGLE(GL_TRIANGLES, &count, GL_UNSIGNED_SHORT, &indices, &instances,
1053                                       1);
1054     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1055 }
1056 
1057 const angle::PlatformParameters platforms[] = {
1058     ES2_D3D9(),  ES2_OPENGL(), ES2_OPENGLES(), ES2_VULKAN(),
1059     ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES(),
1060 };
1061 
1062 const angle::PlatformParameters es2_platforms[] = {
1063     ES2_D3D9(),
1064     ES2_OPENGL(),
1065     ES2_OPENGLES(),
1066     ES2_VULKAN(),
1067 };
1068 
1069 INSTANTIATE_TEST_SUITE_P(
1070     ,
1071     MultiDrawTest,
1072     testing::Combine(
1073         testing::ValuesIn(::angle::FilterTestParams(platforms, ArraySize(platforms))),
1074         testing::Values(DrawIDOption::NoDrawID, DrawIDOption::UseDrawID),
1075         testing::Values(InstancingOption::NoInstancing, InstancingOption::UseInstancing),
1076         testing::Values(BufferDataUsageOption::StaticDraw, BufferDataUsageOption::DynamicDraw)),
1077     PrintToStringParamName());
1078 
1079 INSTANTIATE_TEST_SUITE_P(
1080     ,
1081     MultiDrawNoInstancingSupportTest,
1082     testing::Combine(
1083         testing::ValuesIn(::angle::FilterTestParams(es2_platforms, ArraySize(es2_platforms))),
1084         testing::Values(DrawIDOption::NoDrawID, DrawIDOption::UseDrawID),
1085         testing::Values(InstancingOption::UseInstancing),
1086         testing::Values(BufferDataUsageOption::StaticDraw, BufferDataUsageOption::DynamicDraw)),
1087     PrintToStringParamName());
1088 
1089 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MultiDrawIndirectTest);
1090 
1091 ANGLE_INSTANTIATE_TEST_ES31_AND(MultiDrawIndirectTest,
1092                                 ES31_VULKAN().disable(Feature::SupportsMultiDrawIndirect));
1093 }  // namespace
1094