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