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