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