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 ()__anon76d3c0330111::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_shader_builtin : 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 if (IsGLExtensionRequestable("GL_ANGLE_base_vertex_base_instance_shader_builtin"))
436 {
437 glRequestExtensionANGLE("GL_ANGLE_base_vertex_base_instance_shader_builtin");
438 }
439
440 return true;
441 }
442
requestInstancedExtension()443 bool requestInstancedExtension()
444 {
445 if (IsGLExtensionRequestable("GL_ANGLE_instanced_arrays"))
446 {
447 glRequestExtensionANGLE("GL_ANGLE_instanced_arrays");
448 }
449
450 if (!IsGLExtensionEnabled("GL_ANGLE_instanced_arrays"))
451 {
452 return false;
453 }
454
455 return true;
456 }
457
requestExtensions()458 bool requestExtensions()
459 {
460 if (getClientMajorVersion() <= 2)
461 {
462 if (!requestInstancedExtension())
463 {
464 return false;
465 }
466 }
467 return requestDrawBaseVertexBaseInstanceExtension();
468 }
469
470 // Used for base vertex base instance draw calls
471 std::vector<GLushort> mIndices;
472 std::vector<GLfloat> mVertices;
473 std::vector<GLfloat> mNonIndexedVertices;
474 // Used when gl_BaseInstance is not used
475 std::array<GLfloat, kCountX> mInstancedArrayId;
476 std::array<GLfloat, kCountX> mInstancedArrayColorId;
477 // Used for regular draw calls without base vertex base instance
478 std::vector<GLushort> mRegularIndices;
479 GLint mPositionLoc;
480 GLuint mInstanceIDLoc;
481 GLuint mInstanceColorIDLoc;
482 };
483
484 // Tests that compile a program with the extension succeeds
TEST_P(DrawBaseVertexBaseInstanceTest,CanCompile)485 TEST_P(DrawBaseVertexBaseInstanceTest, CanCompile)
486 {
487 ANGLE_SKIP_TEST_IF(!requestExtensions());
488 GLProgram p0;
489 setupProgram(p0, true, false);
490 GLProgram p1;
491 setupProgram(p1, true, true);
492 GLProgram p2;
493 setupProgram(p2, false, false);
494 GLProgram p3;
495 setupProgram(p3, false, true);
496 }
497
498 // Tests if baseInstance works properly with instanced array with non-zero divisor
TEST_P(DrawBaseVertexBaseInstanceTest,BaseInstanceDivisor)499 TEST_P(DrawBaseVertexBaseInstanceTest, BaseInstanceDivisor)
500 {
501 ANGLE_SKIP_TEST_IF(!requestExtensions());
502 ANGLE_SKIP_TEST_IF(useBaseInstanceBuiltin());
503
504 GLProgram program;
505 setupProgram(program, true, false, true);
506
507 GLBuffer nonIndexedVertexBuffer;
508 setupNonIndexedBuffers(nonIndexedVertexBuffer);
509 setupPositionVertexAttribPointer();
510
511 GLBuffer instanceIDBuffer;
512 GLBuffer instanceColorIDBuffer;
513
514 setupInstanceIDBuffer(instanceIDBuffer);
515 setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
516 setupInstanceColorIDBuffer(instanceColorIDBuffer);
517 setupInstanceIDVertexAttribPointer(mInstanceColorIDLoc);
518
519 doDrawArraysInstancedBaseInstance();
520 EXPECT_GL_NO_ERROR();
521 checkDrawResult(false);
522
523 doDrawArraysBaseInstanceReset();
524 EXPECT_GL_NO_ERROR();
525 checkDrawResult(false, true);
526
527 GLProgram programIndexed;
528 setupProgram(programIndexed, false, false, true);
529
530 GLBuffer indexBuffer;
531 GLBuffer vertexBuffer;
532 setupIndexedBuffers(vertexBuffer, indexBuffer);
533 setupPositionVertexAttribPointer();
534
535 glBindBuffer(GL_ARRAY_BUFFER, instanceIDBuffer);
536 setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
537 glBindBuffer(GL_ARRAY_BUFFER, instanceColorIDBuffer);
538 setupInstanceIDVertexAttribPointer(mInstanceColorIDLoc);
539
540 doDrawElementsInstancedBaseVertexBaseInstance();
541 EXPECT_GL_NO_ERROR();
542 checkDrawResult(true);
543
544 setupRegularIndexedBuffer(indexBuffer);
545 doDrawElementsBaseVertexBaseInstanceReset();
546 EXPECT_GL_NO_ERROR();
547 checkDrawResult(false, true);
548 }
549
550 // Tests basic functionality of glDrawArraysInstancedBaseInstance
TEST_P(DrawBaseVertexBaseInstanceTest,DrawArraysInstancedBaseInstance)551 TEST_P(DrawBaseVertexBaseInstanceTest, DrawArraysInstancedBaseInstance)
552 {
553 // TODO(shrekshao): Temporarily skip this test
554 // before we could try updating win AMD bot driver version
555 // after Lab team fixed issues with ssh into bot machines
556 // Currently this test fail on certain Win7/Win2008Server AMD GPU
557 // with driver version 23.20.185.235 when using OpenGL backend.
558 // This failure couldn't be produced on local Win10 AMD machine with latest driver installed
559 // Same for the MultiDrawArraysInstancedBaseInstance test
560 if (IsAMD() && IsWindows() && IsDesktopOpenGL())
561 {
562 SystemInfo *systemInfo = GetTestSystemInfo();
563 if (!systemInfo->gpus.empty())
564 {
565 ANGLE_SKIP_TEST_IF(0x6613 == systemInfo->gpus[systemInfo->activeGPUIndex].deviceId);
566 }
567 }
568
569 ANGLE_SKIP_TEST_IF(!requestExtensions());
570
571 GLProgram program;
572 setupProgram(program, true);
573
574 GLBuffer vertexBuffer;
575 setupNonIndexedBuffers(vertexBuffer);
576 setupPositionVertexAttribPointer();
577
578 GLBuffer instanceIDBuffer;
579 if (!useBaseInstanceBuiltin())
580 {
581 setupInstanceIDBuffer(instanceIDBuffer);
582 setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
583 }
584
585 doDrawArraysInstancedBaseInstance();
586 EXPECT_GL_NO_ERROR();
587 checkDrawResult(false);
588
589 doDrawArraysBaseInstanceReset();
590 EXPECT_GL_NO_ERROR();
591 checkDrawResult(false, true);
592 }
593
594 // Tests basic functionality of glMultiDrawArraysInstancedBaseInstance
TEST_P(DrawBaseVertexBaseInstanceTest,MultiDrawArraysInstancedBaseInstance)595 TEST_P(DrawBaseVertexBaseInstanceTest, MultiDrawArraysInstancedBaseInstance)
596 {
597 if (IsAMD() && IsWindows() && IsDesktopOpenGL())
598 {
599 SystemInfo *systemInfo = GetTestSystemInfo();
600 if (!(systemInfo->activeGPUIndex < 0 || systemInfo->gpus.empty()))
601 {
602 ANGLE_SKIP_TEST_IF(0x6613 == systemInfo->gpus[systemInfo->activeGPUIndex].deviceId);
603 }
604 }
605
606 ANGLE_SKIP_TEST_IF(!requestExtensions());
607
608 GLProgram program;
609 setupProgram(program, true, true);
610
611 GLBuffer vertexBuffer;
612 setupNonIndexedBuffers(vertexBuffer);
613 setupPositionVertexAttribPointer();
614
615 GLBuffer instanceIDBuffer;
616 if (!useBaseInstanceBuiltin())
617 {
618 setupInstanceIDBuffer(instanceIDBuffer);
619 setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
620 }
621
622 doMultiDrawArraysInstancedBaseInstance();
623 EXPECT_GL_NO_ERROR();
624 checkDrawResult(false);
625
626 doDrawArraysBaseInstanceReset();
627 EXPECT_GL_NO_ERROR();
628 checkDrawResult(false, true);
629 }
630
631 // Tests basic functionality of glDrawElementsInstancedBaseVertexBaseInstance
TEST_P(DrawBaseVertexBaseInstanceTest,DrawElementsInstancedBaseVertexBaseInstance)632 TEST_P(DrawBaseVertexBaseInstanceTest, DrawElementsInstancedBaseVertexBaseInstance)
633 {
634 ANGLE_SKIP_TEST_IF(!requestExtensions());
635
636 GLProgram program;
637 setupProgram(program, false);
638
639 GLBuffer indexBuffer;
640 GLBuffer vertexBuffer;
641 setupIndexedBuffers(vertexBuffer, indexBuffer);
642 setupPositionVertexAttribPointer();
643
644 GLBuffer instanceIDBuffer;
645 if (!useBaseInstanceBuiltin())
646 {
647 setupInstanceIDBuffer(instanceIDBuffer);
648 setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
649 }
650
651 doDrawElementsInstancedBaseVertexBaseInstance();
652 EXPECT_GL_NO_ERROR();
653 checkDrawResult(true);
654
655 setupRegularIndexedBuffer(indexBuffer);
656 doDrawElementsBaseVertexBaseInstanceReset();
657 EXPECT_GL_NO_ERROR();
658 checkDrawResult(true, true);
659 }
660
661 // Tests basic functionality of glMultiDrawElementsInstancedBaseVertexBaseInstance
TEST_P(DrawBaseVertexBaseInstanceTest,MultiDrawElementsInstancedBaseVertexBaseInstance)662 TEST_P(DrawBaseVertexBaseInstanceTest, MultiDrawElementsInstancedBaseVertexBaseInstance)
663 {
664 ANGLE_SKIP_TEST_IF(!requestExtensions());
665
666 GLProgram program;
667 setupProgram(program, false, true);
668
669 GLBuffer indexBuffer;
670 GLBuffer vertexBuffer;
671 setupIndexedBuffers(vertexBuffer, indexBuffer);
672 setupPositionVertexAttribPointer();
673
674 GLBuffer instanceIDBuffer;
675 if (!useBaseInstanceBuiltin())
676 {
677 setupInstanceIDBuffer(instanceIDBuffer);
678 setupInstanceIDVertexAttribPointer(mInstanceIDLoc);
679 }
680
681 doMultiDrawElementsInstancedBaseVertexBaseInstance();
682 EXPECT_GL_NO_ERROR();
683 checkDrawResult(true);
684
685 setupRegularIndexedBuffer(indexBuffer);
686 doDrawElementsBaseVertexBaseInstanceReset();
687 EXPECT_GL_NO_ERROR();
688 checkDrawResult(true, true);
689 }
690
691 const angle::PlatformParameters platforms[] = {
692 ES3_D3D11(),
693 ES3_OPENGL(),
694 ES3_OPENGLES(),
695 ES3_VULKAN(),
696 };
697
698 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DrawBaseVertexBaseInstanceTest);
699 INSTANTIATE_TEST_SUITE_P(
700 ,
701 DrawBaseVertexBaseInstanceTest,
702 testing::Combine(
703 testing::ValuesIn(::angle::FilterTestParams(platforms, ArraySize(platforms))),
704 testing::Values(BaseVertexOption::NoBaseVertex, BaseVertexOption::UseBaseVertex),
705 testing::Values(BaseInstanceOption::NoBaseInstance, BaseInstanceOption::UseBaseInstance),
706 testing::Values(BufferDataUsageOption::StaticDraw, BufferDataUsageOption::DynamicDraw)),
707 PrintToStringParamName());
708
709 } // namespace
710