• 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 ()__anon053ab3b20111::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__anon053ab3b20111::DrawArraysIndirectCommand93     DrawArraysIndirectCommand() : count(0u), instanceCount(0u), first(0u), baseInstance(0u) {}
DrawArraysIndirectCommand__anon053ab3b20111::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__anon053ab3b20111::DrawElementsIndirectCommand105     DrawElementsIndirectCommand()
106         : count(0), primCount(0), firstIndex(0), baseVertex(0), baseInstance(0)
107     {}
DrawElementsIndirectCommand__anon053ab3b20111::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                << ";" << R"(
182     float quad_id = float(id / 2);
183     float color_id = quad_id - (3.0 * floor(quad_id / 3.0));
184     if (color_id == 0.0) {
185       color = vec4(1, 0, 0, 1);
186     } else if (color_id == 1.0) {
187       color = vec4(0, 1, 0, 1);
188     } else {
189       color = vec4(0, 0, 1, 1);
190     }
191 
192     mat3 transform = mat3(1.0);
193 )"
194                << (IsInstancedTest() ? R"(
195     transform[0][0] = 0.5;
196     transform[1][1] = 0.5;
197     if (vInstance == 0.0) {
198 
199     } else if (vInstance == 1.0) {
200         transform[2][0] = 0.5;
201     } else if (vInstance == 2.0) {
202         transform[2][1] = 0.5;
203     } else if (vInstance == 3.0) {
204         transform[2][0] = 0.5;
205         transform[2][1] = 0.5;
206     }
207 )"
208                                      : "")
209                << R"(
210     gl_Position = vec4(transform * vec3(vPosition, 1.0) * 2.0 - 1.0, 1);
211 })";
212 
213         return shader.str();
214     }
215 
FragmentShaderSource()216     std::string FragmentShaderSource()
217     {
218         return
219             R"(precision mediump float;
220             varying vec4 color;
221             void main()
222             {
223                 gl_FragColor = color;
224             })";
225     }
226 
SetupProgram()227     void SetupProgram()
228     {
229         mProgram = CompileProgram(VertexShaderSource().c_str(), FragmentShaderSource().c_str());
230         EXPECT_GL_NO_ERROR();
231         ASSERT_GE(mProgram, 1u);
232         glUseProgram(mProgram);
233         mPositionLoc = glGetAttribLocation(mProgram, "vPosition");
234         mInstanceLoc = glGetAttribLocation(mProgram, "vInstance");
235     }
236 
SetupBuffers()237     void SetupBuffers()
238     {
239         for (uint32_t y = 0; y < kCountY; ++y)
240         {
241             for (uint32_t x = 0; x < kCountX; ++x)
242             {
243                 // v3 ---- v2
244                 // |       |
245                 // |       |
246                 // v0 ---- v1
247                 uint32_t quadIndex         = y * kCountX + x;
248                 GLushort starting_index    = static_cast<GLushort>(4 * quadIndex);
249                 std::array<GLushort, 6> is = {0, 1, 2, 0, 2, 3};
250                 const auto vs              = getQuadVertices(x, y);
251                 for (GLushort i : is)
252                 {
253                     mIndices.push_back(starting_index + i);
254                 }
255 
256                 for (const auto &v : vs)
257                 {
258                     mVertices.insert(mVertices.end(), v.begin(), v.end());
259                 }
260 
261                 for (GLushort i : is)
262                 {
263                     mNonIndexedVertices.insert(mNonIndexedVertices.end(), vs[i].begin(),
264                                                vs[i].end());
265                 }
266             }
267         }
268 
269         std::array<GLfloat, 4> instances{0, 1, 2, 3};
270 
271         glGenBuffers(1, &mNonIndexedVertexBuffer);
272         glBindBuffer(GL_ARRAY_BUFFER, mNonIndexedVertexBuffer);
273         glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mNonIndexedVertices.size(),
274                      mNonIndexedVertices.data(), getBufferDataUsage());
275 
276         glGenBuffers(1, &mVertexBuffer);
277         glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
278         glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mVertices.size(), mVertices.data(),
279                      getBufferDataUsage());
280 
281         glGenBuffers(1, &mIndexBuffer);
282         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
283         glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * mIndices.size(), mIndices.data(),
284                      getBufferDataUsage());
285 
286         glGenBuffers(1, &mInstanceBuffer);
287         glBindBuffer(GL_ARRAY_BUFFER, mInstanceBuffer);
288         glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * instances.size(), instances.data(),
289                      getBufferDataUsage());
290 
291         ASSERT_GL_NO_ERROR();
292     }
293 
DoVertexAttribDivisor(GLint location,GLuint divisor)294     void DoVertexAttribDivisor(GLint location, GLuint divisor)
295     {
296         if (getClientMajorVersion() <= 2)
297         {
298             ASSERT_TRUE(IsGLExtensionEnabled("GL_ANGLE_instanced_arrays"));
299             glVertexAttribDivisorANGLE(location, divisor);
300         }
301         else
302         {
303             glVertexAttribDivisor(location, divisor);
304         }
305     }
306 
DoDrawArrays()307     void DoDrawArrays()
308     {
309         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
310         glBindBuffer(GL_ARRAY_BUFFER, mNonIndexedVertexBuffer);
311         glEnableVertexAttribArray(mPositionLoc);
312         glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
313 
314         std::vector<GLint> firsts(kTriCount);
315         std::vector<GLsizei> counts(kTriCount, 3);
316         for (uint32_t i = 0; i < kTriCount; ++i)
317         {
318             firsts[i] = i * 3;
319         }
320 
321         if (IsInstancedTest())
322         {
323             glBindBuffer(GL_ARRAY_BUFFER, mInstanceBuffer);
324             glEnableVertexAttribArray(mInstanceLoc);
325             glVertexAttribPointer(mInstanceLoc, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
326             DoVertexAttribDivisor(mInstanceLoc, 1);
327             std::vector<GLsizei> instanceCounts(kTriCount, 4);
328             glMultiDrawArraysInstancedANGLE(GL_TRIANGLES, firsts.data(), counts.data(),
329                                             instanceCounts.data(), kTriCount);
330         }
331         else
332         {
333             glMultiDrawArraysANGLE(GL_TRIANGLES, firsts.data(), counts.data(), kTriCount);
334         }
335     }
336 
DoDrawElements()337     void DoDrawElements()
338     {
339         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
340         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
341         glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
342         glEnableVertexAttribArray(mPositionLoc);
343         glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
344 
345         std::vector<GLsizei> counts(kTriCount, 3);
346         std::vector<const GLvoid *> indices(kTriCount);
347         for (uint32_t i = 0; i < kTriCount; ++i)
348         {
349             indices[i] = reinterpret_cast<GLvoid *>(static_cast<uintptr_t>(i * 3 * 2));
350         }
351 
352         if (IsInstancedTest())
353         {
354             glBindBuffer(GL_ARRAY_BUFFER, mInstanceBuffer);
355             glEnableVertexAttribArray(mInstanceLoc);
356             glVertexAttribPointer(mInstanceLoc, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
357             DoVertexAttribDivisor(mInstanceLoc, 1);
358             std::vector<GLsizei> instanceCounts(kTriCount, 4);
359             glMultiDrawElementsInstancedANGLE(GL_TRIANGLES, counts.data(), GL_UNSIGNED_SHORT,
360                                               indices.data(), instanceCounts.data(), kTriCount);
361         }
362         else
363         {
364             glMultiDrawElementsANGLE(GL_TRIANGLES, counts.data(), GL_UNSIGNED_SHORT, indices.data(),
365                                      kTriCount);
366         }
367     }
368 
369     enum class DrawIDOptionOverride
370     {
371         Default,
372         NoDrawID,
373         UseDrawID,
374     };
375 
CheckDrawResult(DrawIDOptionOverride overrideDrawID)376     void CheckDrawResult(DrawIDOptionOverride overrideDrawID)
377     {
378         for (uint32_t y = 0; y < kCountY; ++y)
379         {
380             for (uint32_t x = 0; x < kCountX; ++x)
381             {
382                 uint32_t center_x = x * kTilePixelSize[0] + kTilePixelSize[0] / 2;
383                 uint32_t center_y = y * kTilePixelSize[1] + kTilePixelSize[1] / 2;
384                 uint32_t quadID = IsDrawIDTest() && overrideDrawID != DrawIDOptionOverride::NoDrawID
385                                       ? y * kCountX + x
386                                       : 0;
387                 uint32_t colorID              = quadID % 3u;
388                 std::array<GLColor, 3> colors = {GLColor(255, 0, 0, 255), GLColor(0, 255, 0, 255),
389                                                  GLColor(0, 0, 255, 255)};
390                 GLColor expected              = colors[colorID];
391 
392                 if (IsInstancedTest())
393                 {
394                     EXPECT_PIXEL_RECT_EQ(center_x / 2 - kPixelCheckSize[0] / 4,
395                                          center_y / 2 - kPixelCheckSize[1] / 4,
396                                          kPixelCheckSize[0] / 2, kPixelCheckSize[1] / 2, expected);
397                     EXPECT_PIXEL_RECT_EQ(center_x / 2 - kPixelCheckSize[0] / 4 + kWidth / 2,
398                                          center_y / 2 - kPixelCheckSize[1] / 4,
399                                          kPixelCheckSize[0] / 2, kPixelCheckSize[1] / 2, expected);
400                     EXPECT_PIXEL_RECT_EQ(center_x / 2 - kPixelCheckSize[0] / 4,
401                                          center_y / 2 - kPixelCheckSize[1] / 4 + kHeight / 2,
402                                          kPixelCheckSize[0] / 2, kPixelCheckSize[1] / 2, expected);
403                     EXPECT_PIXEL_RECT_EQ(center_x / 2 - kPixelCheckSize[0] / 4 + kWidth / 2,
404                                          center_y / 2 - kPixelCheckSize[1] / 4 + kHeight / 2,
405                                          kPixelCheckSize[0] / 2, kPixelCheckSize[1] / 2, expected);
406                 }
407                 else
408                 {
409                     EXPECT_PIXEL_RECT_EQ(center_x - kPixelCheckSize[0] / 2,
410                                          center_y - kPixelCheckSize[1] / 2, kPixelCheckSize[0],
411                                          kPixelCheckSize[1], expected);
412                 }
413             }
414         }
415     }
416 
TearDown()417     void TearDown() override
418     {
419         if (mNonIndexedVertexBuffer != 0u)
420         {
421             glDeleteBuffers(1, &mNonIndexedVertexBuffer);
422         }
423         if (mVertexBuffer != 0u)
424         {
425             glDeleteBuffers(1, &mVertexBuffer);
426         }
427         if (mIndexBuffer != 0u)
428         {
429             glDeleteBuffers(1, &mIndexBuffer);
430         }
431         if (mInstanceBuffer != 0u)
432         {
433             glDeleteBuffers(1, &mInstanceBuffer);
434         }
435         if (mProgram != 0)
436         {
437             glDeleteProgram(mProgram);
438         }
439         ANGLETestBase::ANGLETestTearDown();
440     }
441 
requestMultiDrawExtension()442     bool requestMultiDrawExtension() { return EnsureGLExtensionEnabled("GL_ANGLE_multi_draw"); }
443 
requestInstancedExtension()444     bool requestInstancedExtension()
445     {
446         return EnsureGLExtensionEnabled("GL_ANGLE_instanced_arrays");
447     }
448 
requestExtensions()449     bool requestExtensions()
450     {
451         if (IsInstancedTest() && getClientMajorVersion() <= 2)
452         {
453             if (!requestInstancedExtension())
454             {
455                 return false;
456             }
457         }
458         return requestMultiDrawExtension();
459     }
460 
461     std::vector<GLushort> mIndices;
462     std::vector<GLfloat> mVertices;
463     std::vector<GLfloat> mNonIndexedVertices;
464     GLuint mNonIndexedVertexBuffer;
465     GLuint mVertexBuffer;
466     GLuint mIndexBuffer;
467     GLuint mInstanceBuffer;
468     GLuint mProgram;
469     GLint mPositionLoc;
470     GLint mInstanceLoc;
471 };
472 
473 class MultiDrawTestES3 : public MultiDrawTest
474 {};
475 
476 class MultiDrawNoInstancingSupportTest : public MultiDrawTest
477 {
SetUp()478     void SetUp() override
479     {
480         ASSERT_LE(getClientMajorVersion(), 2);
481         ASSERT_TRUE(IsInstancedTest());
482         MultiDrawTest::SetUp();
483     }
484 };
485 
486 // The tests in MultiDrawIndirectTest check the correctness
487 // of the EXT_multi_draw_indirect extension.
488 // 4 magenta triangles are drawn at the corners of the screen
489 // in different orders from the same vertex and index arrays.
490 class MultiDrawIndirectTest : public ANGLETestBase,
491                               public ::testing::TestWithParam<MultiDrawIndirectTestParams>
492 {
493   protected:
MultiDrawIndirectTest()494     MultiDrawIndirectTest()
495         : ANGLETestBase(GetParam()),
496           mPositionLoc(0u),
497           mColorLoc(0u),
498           mVertexBuffer(0u),
499           mColorBuffer(0u),
500           mIndexBuffer(0u),
501           mIndirectBuffer(0u),
502           mProgram(0u)
503     {
504         setWindowWidth(kWidth);
505         setWindowHeight(kHeight);
506         setConfigRedBits(8);
507         setConfigGreenBits(8);
508         setConfigBlueBits(8);
509         setConfigAlphaBits(8);
510     }
511 
SetUp()512     void SetUp() override { ANGLETestBase::ANGLETestSetUp(); }
513 
SetupProgramIndirect(bool isMultiColor)514     void SetupProgramIndirect(bool isMultiColor)
515     {
516         // Define the vertex and fragment shaders
517         std::stringstream kVS;
518         kVS << R"(#version 310 es
519 in vec3 aPos;
520 )"
521             << (isMultiColor ? R"(in vec4 aColor;
522 out vec4 vColor;)"
523                              : "")
524             << R"(
525 void main()
526 {
527     gl_Position = vec4(aPos.x, aPos.y, 0, 1);
528 )" << (isMultiColor ? R"(vColor = vec4(aColor.x, aColor.y, aColor.z, 1.0);)" : "")
529             << R"(
530 })";
531 
532         std::stringstream kFS;
533         kFS << R"(#version 310 es
534 precision mediump float;
535 )"
536             << (isMultiColor ? R"(in vec4 vColor;
537 )"
538                              : "")
539             << R"(
540 out vec4 colorOut;
541 void main()
542 {
543 )" << (isMultiColor ? R"(colorOut = vColor;)" : R"(colorOut = vec4(1.0, 0.0, 1.0, 1.0);)")
544             << R"(
545 })";
546         mProgram = CompileProgram(kVS.str().c_str(), kFS.str().c_str());
547         EXPECT_GL_NO_ERROR();
548         ASSERT_GE(mProgram, 1u);
549         glUseProgram(mProgram);
550         mPositionLoc = glGetAttribLocation(mProgram, "aPos");
551         mColorLoc    = glGetAttribLocation(mProgram, "aColor");
552     }
553 
TearDown()554     void TearDown() override
555     {
556         if (mVertexBuffer != 0u)
557         {
558             glDeleteBuffers(1, &mVertexBuffer);
559         }
560         if (mColorBuffer != 0u)
561         {
562             glDeleteBuffers(1, &mColorBuffer);
563         }
564         if (mIndexBuffer != 0u)
565         {
566             glDeleteBuffers(1, &mIndexBuffer);
567         }
568         if (mProgram != 0)
569         {
570             glDeleteProgram(mProgram);
571         }
572         if (mIndirectBuffer != 0u)
573         {
574             glDeleteBuffers(1, &mIndirectBuffer);
575         }
576         ANGLETestBase::ANGLETestTearDown();
577     }
578 
579     GLint mPositionLoc;
580     GLint mColorLoc;
581     GLuint mVertexBuffer;
582     GLuint mColorBuffer;
583     GLuint mIndexBuffer;
584     GLuint mIndirectBuffer;
585     GLuint mProgram;
586 };
587 
588 // glMultiDraw*ANGLE are emulated and should always be available
TEST_P(MultiDrawTest,RequestExtension)589 TEST_P(MultiDrawTest, RequestExtension)
590 {
591     EXPECT_TRUE(requestMultiDrawExtension());
592 }
593 
594 // Test that compile a program with the extension succeeds
TEST_P(MultiDrawTest,CanCompile)595 TEST_P(MultiDrawTest, CanCompile)
596 {
597     ANGLE_SKIP_TEST_IF(!requestExtensions());
598     SetupProgram();
599 }
600 
601 // Tests basic functionality of glMultiDrawArraysANGLE
TEST_P(MultiDrawTest,MultiDrawArrays)602 TEST_P(MultiDrawTest, MultiDrawArrays)
603 {
604     ANGLE_SKIP_TEST_IF(!requestExtensions());
605 
606     // http://anglebug.com/5265
607     ANGLE_SKIP_TEST_IF(IsInstancedTest() && IsMac() && IsIntelUHD630Mobile() && IsDesktopOpenGL());
608 
609     SetupBuffers();
610     SetupProgram();
611     DoDrawArrays();
612     EXPECT_GL_NO_ERROR();
613     CheckDrawResult(DrawIDOptionOverride::Default);
614 }
615 
616 // Tests basic functionality of glMultiDrawArraysANGLE after a failed program relink
TEST_P(MultiDrawTestES3,MultiDrawArraysAfterFailedRelink)617 TEST_P(MultiDrawTestES3, MultiDrawArraysAfterFailedRelink)
618 {
619     ANGLE_SKIP_TEST_IF(!requestExtensions());
620 
621     // http://anglebug.com/5265
622     ANGLE_SKIP_TEST_IF(IsInstancedTest() && IsMac() && IsIntelUHD630Mobile() && IsDesktopOpenGL());
623 
624     SetupBuffers();
625     SetupProgram();
626 
627     // mProgram is already installed.  Destroy its state by a failed relink.
628     const char *tfVaryings = "invalidvaryingname";
629     glTransformFeedbackVaryings(mProgram, 1, &tfVaryings, GL_SEPARATE_ATTRIBS);
630     glLinkProgram(mProgram);
631     GLint linkStatus = 0;
632     glGetProgramiv(mProgram, GL_LINK_STATUS, &linkStatus);
633     ASSERT_GL_NO_ERROR();
634     ASSERT_EQ(linkStatus, GL_FALSE);
635 
636     DoDrawArrays();
637     EXPECT_GL_NO_ERROR();
638     CheckDrawResult(DrawIDOptionOverride::Default);
639 }
640 
641 // Tests basic functionality of glMultiDrawElementsANGLE
TEST_P(MultiDrawTest,MultiDrawElements)642 TEST_P(MultiDrawTest, MultiDrawElements)
643 {
644     ANGLE_SKIP_TEST_IF(!requestExtensions());
645     SetupBuffers();
646     SetupProgram();
647     DoDrawElements();
648     EXPECT_GL_NO_ERROR();
649     CheckDrawResult(DrawIDOptionOverride::Default);
650 }
651 
652 // Tests that glMultiDrawArraysANGLE followed by glDrawArrays works.  gl_DrawID in the second call
653 // must be 0.
TEST_P(MultiDrawTest,MultiDrawArraysThenDrawArrays)654 TEST_P(MultiDrawTest, MultiDrawArraysThenDrawArrays)
655 {
656     ANGLE_SKIP_TEST_IF(!requestExtensions());
657 
658     // http://anglebug.com/5265
659     ANGLE_SKIP_TEST_IF(IsInstancedTest() && IsMac() && IsIntelUHD630Mobile() && IsDesktopOpenGL());
660 
661     SetupBuffers();
662     SetupProgram();
663     DoDrawArrays();
664     EXPECT_GL_NO_ERROR();
665     CheckDrawResult(DrawIDOptionOverride::Default);
666 
667     if (IsInstancedTest())
668     {
669         ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_instanced_arrays") &&
670                            !IsGLExtensionEnabled("GL_ANGLE_instanced_arrays"));
671         if (IsGLExtensionEnabled("GL_EXT_instanced_arrays"))
672         {
673             glDrawArraysInstancedEXT(GL_TRIANGLES, 0, 3 * kTriCount, 4);
674         }
675         else
676         {
677             glDrawArraysInstancedANGLE(GL_TRIANGLES, 0, 3 * kTriCount, 4);
678         }
679         ASSERT_GL_NO_ERROR();
680     }
681     else
682     {
683         glDrawArrays(GL_TRIANGLES, 0, 3 * kTriCount);
684         ASSERT_GL_NO_ERROR();
685     }
686     CheckDrawResult(DrawIDOptionOverride::NoDrawID);
687 }
688 
689 // Tests basic functionality of glMultiDrawArraysIndirectEXT
TEST_P(MultiDrawIndirectTest,MultiDrawArraysIndirect)690 TEST_P(MultiDrawIndirectTest, MultiDrawArraysIndirect)
691 {
692     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multi_draw_indirect"));
693 
694     // Set up the vertex array
695     const GLint triangleCount           = 4;
696     const std::vector<GLfloat> vertices = {
697         -1, 1,  0, -1, 0, 0, 0, 1,  0, 1, 1,  0, 1, 0,  0, 0, 1, 0,
698         -1, -1, 0, -1, 0, 0, 0, -1, 0, 1, -1, 0, 0, -1, 0, 1, 0, 0,
699     };
700 
701     // Set up the vertex buffer
702     GLVertexArray vao;
703     glBindVertexArray(vao);
704 
705     glGenBuffers(1, &mVertexBuffer);
706     glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
707     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * vertices.size(), vertices.data(),
708                  GL_STATIC_DRAW);
709     EXPECT_GL_NO_ERROR();
710 
711     // Generate program
712     SetupProgramIndirect(false);
713 
714     // Set up the vertex array format
715     glEnableVertexAttribArray(mPositionLoc);
716     glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
717     EXPECT_GL_NO_ERROR();
718 
719     // Set up the indirect data array
720     std::array<DrawArraysIndirectCommand, triangleCount> indirectData;
721     const GLsizei icSize = sizeof(DrawArraysIndirectCommand);
722     for (auto i = 0; i < triangleCount; i++)
723     {
724         indirectData[i] = DrawArraysIndirectCommand(3, 1, 3 * i, i);
725     }
726 
727     glGenBuffers(1, &mIndirectBuffer);
728     glBindBuffer(GL_DRAW_INDIRECT_BUFFER, mIndirectBuffer);
729     glBufferData(GL_DRAW_INDIRECT_BUFFER, icSize * indirectData.size(), indirectData.data(),
730                  GL_STATIC_DRAW);
731     EXPECT_GL_NO_ERROR();
732 
733     // Invalid value check for drawcount and stride
734     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
735     glMultiDrawArraysIndirectEXT(GL_TRIANGLES, nullptr, 0, 0);
736     EXPECT_GL_ERROR(GL_INVALID_VALUE);
737     glMultiDrawArraysIndirectEXT(GL_TRIANGLES, nullptr, -1, 0);
738     EXPECT_GL_ERROR(GL_INVALID_VALUE);
739     glMultiDrawArraysIndirectEXT(GL_TRIANGLES, nullptr, 1, 2);
740     EXPECT_GL_ERROR(GL_INVALID_VALUE);
741 
742     // Check the error from sourcing beyond the allocated buffer size
743     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
744     glMultiDrawArraysIndirectEXT(
745         GL_TRIANGLES,
746         reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize * triangleCount)), 1, 0);
747     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
748 
749     // Draw all triangles using glMultiDrawArraysIndirect
750     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
751     glMultiDrawArraysIndirectEXT(GL_TRIANGLES, nullptr, triangleCount, 0);
752     EXPECT_GL_NO_ERROR();
753 
754     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
755     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::magenta);
756     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::magenta);
757     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::magenta);
758     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
759 
760     // Draw the triangles in different order
761     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
762     glMultiDrawArraysIndirectEXT(GL_TRIANGLES, nullptr, 1, 0);
763     glMultiDrawArraysIndirectEXT(GL_TRIANGLES,
764                                  reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize * 2)),
765                                  triangleCount - 2, 0);
766     glMultiDrawArraysIndirectEXT(
767         GL_TRIANGLES, reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize)), 1, 0);
768     EXPECT_GL_NO_ERROR();
769 
770     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
771     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::magenta);
772     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::magenta);
773     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::magenta);
774     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
775 
776     // Draw the triangles partially using stride
777     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
778     glMultiDrawArraysIndirectEXT(GL_TRIANGLES, nullptr, 2, icSize * 3);
779     EXPECT_GL_NO_ERROR();
780 
781     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
782     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::magenta);
783     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::magenta);
784     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::transparentBlack);
785     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
786 }
787 
788 // Tests basic functionality of glMultiDrawElementsIndirectEXT
TEST_P(MultiDrawIndirectTest,MultiDrawElementsIndirect)789 TEST_P(MultiDrawIndirectTest, MultiDrawElementsIndirect)
790 {
791     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multi_draw_indirect"));
792 
793     // Set up the vertex array
794     const GLint triangleCount           = 4;
795     const std::vector<GLfloat> vertices = {
796         -1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, -1, 0, 0, -1, 0, -1, -1, 0, -1, 0, 0,
797     };
798     const std::vector<GLuint> indices = {
799         1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 0, 1,
800     };
801 
802     // Set up the vertex and index buffers
803     GLVertexArray vao;
804     glBindVertexArray(vao);
805 
806     glGenBuffers(1, &mVertexBuffer);
807     glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
808     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * vertices.size(), vertices.data(),
809                  GL_STATIC_DRAW);
810 
811     glGenBuffers(1, &mIndexBuffer);
812     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
813     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indices.size(), indices.data(),
814                  GL_STATIC_DRAW);
815     EXPECT_GL_NO_ERROR();
816 
817     // Generate program
818     SetupProgramIndirect(false);
819 
820     // Set up the vertex array format
821     glEnableVertexAttribArray(mPositionLoc);
822     glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
823     EXPECT_GL_NO_ERROR();
824 
825     // Set up the indirect data array
826     std::array<DrawElementsIndirectCommand, triangleCount> indirectData;
827     const GLsizei icSize = sizeof(DrawElementsIndirectCommand);
828     for (auto i = 0; i < triangleCount; i++)
829     {
830         indirectData[i] = DrawElementsIndirectCommand(3, 1, 3 * i, 0, i);
831     }
832 
833     glGenBuffers(1, &mIndirectBuffer);
834     glBindBuffer(GL_DRAW_INDIRECT_BUFFER, mIndirectBuffer);
835     glBufferData(GL_DRAW_INDIRECT_BUFFER, icSize * indirectData.size(), indirectData.data(),
836                  GL_STATIC_DRAW);
837     EXPECT_GL_NO_ERROR();
838 
839     // Invalid value check for drawcount and stride
840     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
841     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr, 0, 0);
842     EXPECT_GL_ERROR(GL_INVALID_VALUE);
843     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr, -1, 0);
844     EXPECT_GL_ERROR(GL_INVALID_VALUE);
845     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr, 1, 2);
846     EXPECT_GL_ERROR(GL_INVALID_VALUE);
847 
848     // Check the error from sourcing beyond the allocated buffer size
849     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
850     glMultiDrawElementsIndirectEXT(
851         GL_TRIANGLES, GL_UNSIGNED_INT,
852         reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize * triangleCount)), 1, 0);
853     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
854 
855     // Draw all triangles using glMultiDrawElementsIndirect
856     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
857     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr, triangleCount, 0);
858     EXPECT_GL_NO_ERROR();
859 
860     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
861     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::magenta);
862     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::magenta);
863     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::magenta);
864     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
865 
866     // Draw the triangles in a different order
867     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
868     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr, 1, 0);
869     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_INT,
870                                    reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize)),
871                                    triangleCount - 2, 0);
872     glMultiDrawElementsIndirectEXT(
873         GL_TRIANGLES, GL_UNSIGNED_INT,
874         reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize * 3)), 1, 0);
875     EXPECT_GL_NO_ERROR();
876 
877     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
878     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::magenta);
879     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::magenta);
880     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::magenta);
881     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
882 
883     // Draw the triangles partially using stride
884     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
885     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr, 2, icSize * 3);
886     EXPECT_GL_NO_ERROR();
887 
888     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
889     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::magenta);
890     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::transparentBlack);
891     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::magenta);
892     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
893 }
894 
895 // Test functionality glMultiDrawElementsIndirectEXT with unsigned short
896 // indices and instanced attributes.
TEST_P(MultiDrawIndirectTest,MultiDrawElementsIndirectInstancedUshort)897 TEST_P(MultiDrawIndirectTest, MultiDrawElementsIndirectInstancedUshort)
898 {
899     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multi_draw_indirect"));
900 
901     // Set up the vertex array
902     const GLint triangleCount           = 4;
903     const std::vector<GLfloat> vertices = {
904         -1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, -1, 0, 0, -1, 0, -1, -1, 0, -1, 0, 0,
905     };
906     const std::vector<GLushort> indices = {
907         1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 0, 1,
908     };
909     const std::vector<GLuint> instancedColor = {GLColor::white.asUint(), GLColor::red.asUint(),
910                                                 GLColor::green.asUint(), GLColor::blue.asUint()};
911 
912     // Generate program
913     SetupProgramIndirect(true);
914 
915     // Set up the vertex and index buffers
916     GLVertexArray vao;
917     glBindVertexArray(vao);
918 
919     glGenBuffers(1, &mVertexBuffer);
920     glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
921     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * vertices.size(), vertices.data(),
922                  GL_STATIC_DRAW);
923     glEnableVertexAttribArray(mPositionLoc);
924     glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
925 
926     GLBuffer instanceBuffer;
927     glBindBuffer(GL_ARRAY_BUFFER, instanceBuffer);
928     glBufferData(GL_ARRAY_BUFFER, sizeof(GLuint) * instancedColor.size(), instancedColor.data(),
929                  GL_STATIC_DRAW);
930     glEnableVertexAttribArray(mColorLoc);
931     glVertexAttribPointer(mColorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
932     glVertexAttribDivisor(mColorLoc, 1);
933 
934     glGenBuffers(1, &mIndexBuffer);
935     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
936     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * indices.size(), indices.data(),
937                  GL_STATIC_DRAW);
938     EXPECT_GL_NO_ERROR();
939 
940     // Set up the indirect data array
941     std::array<DrawElementsIndirectCommand, triangleCount> indirectData;
942     const GLsizei icSize = sizeof(DrawElementsIndirectCommand);
943     for (auto i = 0; i < triangleCount; i++)
944     {
945         indirectData[i] = DrawElementsIndirectCommand(3, 1, 3 * i, 0, i);
946     }
947 
948     glGenBuffers(1, &mIndirectBuffer);
949     glBindBuffer(GL_DRAW_INDIRECT_BUFFER, mIndirectBuffer);
950     glBufferData(GL_DRAW_INDIRECT_BUFFER, icSize * indirectData.size(), indirectData.data(),
951                  GL_STATIC_DRAW);
952     EXPECT_GL_NO_ERROR();
953 
954     // Invalid value check for drawcount and stride
955     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
956     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_SHORT, nullptr, 0, 0);
957     EXPECT_GL_ERROR(GL_INVALID_VALUE);
958     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_SHORT, nullptr, -1, 0);
959     EXPECT_GL_ERROR(GL_INVALID_VALUE);
960     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_SHORT, nullptr, 1, 2);
961     EXPECT_GL_ERROR(GL_INVALID_VALUE);
962 
963     // Check the error from sourcing beyond the allocated buffer size
964     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
965     glMultiDrawElementsIndirectEXT(
966         GL_TRIANGLES, GL_UNSIGNED_SHORT,
967         reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize * triangleCount)), 1, 0);
968     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
969 
970     // Draw all triangles using glMultiDrawElementsIndirect
971     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
972     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_SHORT, nullptr, triangleCount, 0);
973     EXPECT_GL_NO_ERROR();
974 
975     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
976     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::blue);
977     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::red);
978     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::white);
979     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
980 
981     // Draw the triangles in a different order
982     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
983     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_SHORT, nullptr, 1, 0);
984     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_SHORT,
985                                    reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize)),
986                                    triangleCount - 2, 0);
987     glMultiDrawElementsIndirectEXT(
988         GL_TRIANGLES, GL_UNSIGNED_SHORT,
989         reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize * 3)), 1, 0);
990     EXPECT_GL_NO_ERROR();
991 
992     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
993     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::blue);
994     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::red);
995     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::white);
996     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
997 
998     // Draw the triangles partially using stride
999     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1000     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_SHORT, nullptr, 2, icSize * 3);
1001     EXPECT_GL_NO_ERROR();
1002 
1003     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
1004     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::blue);
1005     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::transparentBlack);
1006     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::white);
1007     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
1008 }
1009 
1010 // Tests functionality of glMultiDrawElementsIndirectEXT with more than one triangle in one element
1011 // of the indirect buffer.
TEST_P(MultiDrawIndirectTest,MultiDrawElementsIndirectMultipleTriangles)1012 TEST_P(MultiDrawIndirectTest, MultiDrawElementsIndirectMultipleTriangles)
1013 {
1014     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multi_draw_indirect"));
1015 
1016     // Set up the vertex array
1017     const GLint triangleCount           = 4;
1018     const std::vector<GLfloat> vertices = {
1019         -1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, -1, 0, 0, -1, 0, -1, -1, 0, -1, 0, 0,
1020     };
1021     const std::vector<GLuint> indices = {
1022         1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 0, 1,
1023     };
1024 
1025     // Set up the vertex and index buffers
1026     GLVertexArray vao;
1027     glBindVertexArray(vao);
1028 
1029     glGenBuffers(1, &mVertexBuffer);
1030     glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
1031     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * vertices.size(), vertices.data(),
1032                  GL_STATIC_DRAW);
1033 
1034     glGenBuffers(1, &mIndexBuffer);
1035     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
1036     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indices.size(), indices.data(),
1037                  GL_STATIC_DRAW);
1038     EXPECT_GL_NO_ERROR();
1039 
1040     // Generate program
1041     SetupProgramIndirect(false);
1042 
1043     // Set up the vertex array format
1044     glEnableVertexAttribArray(mPositionLoc);
1045     glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1046     EXPECT_GL_NO_ERROR();
1047 
1048     // Set up the indirect data array; first element represents two triangles.
1049     std::array<DrawElementsIndirectCommand, triangleCount - 1> indirectData;
1050     const GLsizei icSize = sizeof(DrawElementsIndirectCommand);
1051     for (auto i = 0; i < triangleCount - 1; i++)
1052     {
1053         if (i == 0)
1054         {
1055             indirectData[i] = DrawElementsIndirectCommand(6, 2, 0, 0, i);
1056         }
1057         else
1058         {
1059             indirectData[i] = DrawElementsIndirectCommand(3, 1, 3 * (i + 1), 0, i);
1060         }
1061     }
1062 
1063     glGenBuffers(1, &mIndirectBuffer);
1064     glBindBuffer(GL_DRAW_INDIRECT_BUFFER, mIndirectBuffer);
1065     glBufferData(GL_DRAW_INDIRECT_BUFFER, icSize * indirectData.size(), indirectData.data(),
1066                  GL_STATIC_DRAW);
1067     EXPECT_GL_NO_ERROR();
1068 
1069     // Draw all triangles using glMultiDrawElementsIndirect
1070     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1071     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr, triangleCount - 1, 0);
1072     EXPECT_GL_NO_ERROR();
1073 
1074     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
1075     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::magenta);
1076     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::magenta);
1077     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::magenta);
1078     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
1079 }
1080 
1081 // Tests glMultiDrawElementsIndirectEXT with glMultiDrawElementsANGLE to see if the index buffer
1082 // offset is being reset.
TEST_P(MultiDrawIndirectTest,MultiDrawElementsIndirectCheckBufferOffset)1083 TEST_P(MultiDrawIndirectTest, MultiDrawElementsIndirectCheckBufferOffset)
1084 {
1085     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multi_draw_indirect"));
1086 
1087     // Set up the vertex array
1088     const GLint triangleCount           = 4;
1089     const std::vector<GLfloat> vertices = {
1090         -1, 0, 0, -1, 1,  0, 0, 1,  0, 0, 1,  0, 1,  1,  0, 1,  0, 0,
1091         1,  0, 0, 1,  -1, 0, 0, -1, 0, 0, -1, 0, -1, -1, 0, -1, 0, 0,
1092     };
1093     const std::vector<GLfloat> colors = {
1094         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,
1095         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,
1096     };
1097     const std::vector<GLuint> indices = {
1098         3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2,
1099     };
1100 
1101     // Set up the vertex and index buffers
1102     GLVertexArray vao;
1103     glBindVertexArray(vao);
1104 
1105     glGenBuffers(1, &mVertexBuffer);
1106     glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
1107     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * vertices.size(), vertices.data(),
1108                  GL_STATIC_DRAW);
1109 
1110     glGenBuffers(1, &mColorBuffer);
1111     glBindBuffer(GL_ARRAY_BUFFER, mColorBuffer);
1112     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * colors.size(), colors.data(), GL_STATIC_DRAW);
1113 
1114     glGenBuffers(1, &mIndexBuffer);
1115     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
1116     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indices.size(), indices.data(),
1117                  GL_STATIC_DRAW);
1118     EXPECT_GL_NO_ERROR();
1119 
1120     // Generate program
1121     SetupProgramIndirect(true);
1122 
1123     // Set up the vertex array format
1124     glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
1125     glEnableVertexAttribArray(mPositionLoc);
1126     glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1127     EXPECT_GL_NO_ERROR();
1128 
1129     glBindBuffer(GL_ARRAY_BUFFER, mColorBuffer);
1130     glEnableVertexAttribArray(mColorLoc);
1131     glVertexAttribPointer(mColorLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1132     EXPECT_GL_NO_ERROR();
1133 
1134     // Set up the arrays for the direct draw
1135     std::vector<GLsizei> counts(triangleCount, 3);
1136     std::vector<const GLvoid *> indicesDirect(triangleCount);
1137     for (auto i = 0; i < triangleCount; i++)
1138     {
1139         indicesDirect[i] =
1140             reinterpret_cast<GLvoid *>(static_cast<uintptr_t>(i * 3 * sizeof(GLuint)));
1141     }
1142 
1143     // Set up the indirect data array for indirect draw
1144     std::array<DrawElementsIndirectCommand, triangleCount> indirectData;
1145     const GLsizei icSize = sizeof(DrawElementsIndirectCommand);
1146     for (auto i = 0; i < triangleCount; i++)
1147     {
1148         indirectData[i] = DrawElementsIndirectCommand(3, 1, 3 * i, 0, i);
1149     }
1150 
1151     glGenBuffers(1, &mIndirectBuffer);
1152     glBindBuffer(GL_DRAW_INDIRECT_BUFFER, mIndirectBuffer);
1153     glBufferData(GL_DRAW_INDIRECT_BUFFER, icSize * indirectData.size(), indirectData.data(),
1154                  GL_STATIC_DRAW);
1155     EXPECT_GL_NO_ERROR();
1156 
1157     // Draw using glMultiDrawElementsIndirect
1158     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1159     glMultiDrawElementsIndirectEXT(
1160         GL_TRIANGLES, GL_UNSIGNED_INT,
1161         reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize * 2)), triangleCount - 2, 0);
1162     EXPECT_GL_NO_ERROR();
1163 
1164     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
1165     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::red);
1166     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::transparentBlack);
1167     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::transparentBlack);
1168     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
1169 
1170     // Draw using glMultiDrawElementsANGLE
1171     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1172     glMultiDrawElementsANGLE(GL_TRIANGLES, counts.data(), GL_UNSIGNED_INT, indicesDirect.data(),
1173                              triangleCount);
1174     EXPECT_GL_NO_ERROR();
1175 
1176     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
1177     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::red);
1178     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::blue);
1179     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::green);
1180     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
1181 
1182     // Draw using glMultiDrawElementsANGLE again
1183     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1184     glMultiDrawElementsANGLE(GL_TRIANGLES, counts.data(), GL_UNSIGNED_INT, indicesDirect.data(),
1185                              triangleCount - 1);
1186     EXPECT_GL_NO_ERROR();
1187 
1188     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
1189     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::transparentBlack);
1190     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::blue);
1191     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::green);
1192     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
1193 
1194     // Draw using glMultiDrawElementsIndirect again
1195     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1196     glMultiDrawElementsIndirectEXT(
1197         GL_TRIANGLES, GL_UNSIGNED_INT,
1198         reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize * 3)), triangleCount - 3, 0);
1199     EXPECT_GL_NO_ERROR();
1200 
1201     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
1202     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::red);
1203     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::transparentBlack);
1204     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::transparentBlack);
1205     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
1206 
1207     // Draw using glMultiDrawElementsIndirect one more time
1208     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1209     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr, triangleCount, 0);
1210     EXPECT_GL_NO_ERROR();
1211 
1212     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
1213     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::red);
1214     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::blue);
1215     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::green);
1216     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
1217 }
1218 
1219 // Check that glMultiDraw*Instanced without instancing support results in GL_INVALID_OPERATION
TEST_P(MultiDrawNoInstancingSupportTest,InvalidOperation)1220 TEST_P(MultiDrawNoInstancingSupportTest, InvalidOperation)
1221 {
1222     ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_ANGLE_instanced_arrays"));
1223     requestMultiDrawExtension();
1224     SetupBuffers();
1225     SetupProgram();
1226 
1227     GLint first       = 0;
1228     GLsizei count     = 3;
1229     GLvoid *indices   = nullptr;
1230     GLsizei instances = 1;
1231 
1232     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1233     glBindBuffer(GL_ARRAY_BUFFER, mNonIndexedVertexBuffer);
1234     glEnableVertexAttribArray(mPositionLoc);
1235     glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1236     glMultiDrawArraysInstancedANGLE(GL_TRIANGLES, &first, &count, &instances, 1);
1237     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1238 
1239     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1240     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
1241     glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
1242     glEnableVertexAttribArray(mPositionLoc);
1243     glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1244     glMultiDrawElementsInstancedANGLE(GL_TRIANGLES, &count, GL_UNSIGNED_SHORT, &indices, &instances,
1245                                       1);
1246     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1247 }
1248 
1249 ANGLE_INSTANTIATE_TEST_COMBINE_3(MultiDrawTest,
1250                                  PrintToStringParamName(),
1251                                  testing::Values(DrawIDOption::NoDrawID, DrawIDOption::UseDrawID),
1252                                  testing::Values(InstancingOption::NoInstancing,
1253                                                  InstancingOption::UseInstancing),
1254                                  testing::Values(BufferDataUsageOption::StaticDraw,
1255                                                  BufferDataUsageOption::DynamicDraw),
1256                                  ANGLE_ALL_TEST_PLATFORMS_ES2,
1257                                  ANGLE_ALL_TEST_PLATFORMS_ES3);
1258 
1259 ANGLE_INSTANTIATE_TEST_COMBINE_3(MultiDrawNoInstancingSupportTest,
1260                                  PrintToStringParamName(),
1261                                  testing::Values(DrawIDOption::NoDrawID, DrawIDOption::UseDrawID),
1262                                  testing::Values(InstancingOption::UseInstancing),
1263                                  testing::Values(BufferDataUsageOption::StaticDraw,
1264                                                  BufferDataUsageOption::DynamicDraw),
1265                                  ANGLE_ALL_TEST_PLATFORMS_ES2);
1266 
1267 ANGLE_INSTANTIATE_TEST_COMBINE_3(MultiDrawTestES3,
1268                                  PrintToStringParamName(),
1269                                  testing::Values(DrawIDOption::NoDrawID, DrawIDOption::UseDrawID),
1270                                  testing::Values(InstancingOption::NoInstancing,
1271                                                  InstancingOption::UseInstancing),
1272                                  testing::Values(BufferDataUsageOption::StaticDraw,
1273                                                  BufferDataUsageOption::DynamicDraw),
1274                                  ANGLE_ALL_TEST_PLATFORMS_ES3);
1275 
1276 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MultiDrawIndirectTest);
1277 ANGLE_INSTANTIATE_TEST_ES31_AND(MultiDrawIndirectTest,
1278                                 ES31_VULKAN().disable(Feature::SupportsMultiDrawIndirect));
1279 }  // namespace
1280