1 //
2 // Copyright 2017 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 // MultiviewPerfTest:
7 // Performance tests for multiview rendering.
8 // - MultiviewCPUBoundBenchmark issues many draw calls and state changes to stress the CPU.
9 // - MultiviewGPUBoundBenchmark draws half a million quads with multiple attributes per vertex in
10 // order to stress the GPU's memory system.
11 //
12
13 #include "ANGLEPerfTest.h"
14 #include "common/vector_utils.h"
15 #include "platform/autogen/FeaturesD3D_autogen.h"
16 #include "test_utils/MultiviewTest.h"
17 #include "test_utils/gl_raii.h"
18 #include "util/shader_utils.h"
19
20 #include <string.h>
21
22 using namespace angle;
23
24 namespace
25 {
26
GetShaderExtensionHeader(bool usesMultiview,int numViews,GLenum shaderType,ExtensionName multiviewExtension)27 std::string GetShaderExtensionHeader(bool usesMultiview,
28 int numViews,
29 GLenum shaderType,
30 ExtensionName multiviewExtension)
31 {
32 if (!usesMultiview)
33 {
34 return "";
35 }
36
37 std::string ext;
38 switch (multiviewExtension)
39 {
40 case multiview:
41 ext = "GL_OVR_multiview";
42 break;
43 case multiview2:
44 ext = "GL_OVR_multiview2";
45 break;
46 default:
47 ext = "extension_error";
48 }
49
50 if (shaderType == GL_VERTEX_SHADER)
51 {
52 return "#extension " + ext + " : require\nlayout(num_views = " + ToString(numViews) +
53 ") in;\n";
54 }
55 return "#extension " + ext + " : require\n";
56 }
57
58 struct Vertex
59 {
60 Vector4 position;
61 Vector4 colorAttributeData[6];
62 };
63
64 enum class MultiviewOption
65 {
66 NoAcceleration,
67 InstancedMultiviewVertexShader,
68 InstancedMultiviewGeometryShader,
69
70 Unspecified
71 };
72
73 using MultiviewPerfWorkload = std::pair<int, int>;
74
75 struct MultiviewPerfParams final : public RenderTestParams
76 {
MultiviewPerfParams__anona6d097080111::MultiviewPerfParams77 MultiviewPerfParams(const EGLPlatformParameters &platformParametersIn,
78 const MultiviewPerfWorkload &workloadIn,
79 MultiviewOption multiviewOptionIn,
80 ExtensionName multiviewExtensionIn)
81 {
82 iterationsPerStep = 1;
83 majorVersion = 3;
84 minorVersion = 0;
85 eglParameters = platformParametersIn;
86 windowWidth = workloadIn.first;
87 windowHeight = workloadIn.second;
88 multiviewOption = multiviewOptionIn;
89 numViews = 2;
90 multiviewExtension = multiviewExtensionIn;
91
92 if (multiviewOption == MultiviewOption::InstancedMultiviewGeometryShader)
93 {
94 eglParameters.enable(Feature::SelectViewInGeometryShader);
95 }
96 }
97
story__anona6d097080111::MultiviewPerfParams98 std::string story() const override
99 {
100 std::string name = RenderTestParams::story();
101 switch (multiviewOption)
102 {
103 case MultiviewOption::NoAcceleration:
104 name += "_no_acc";
105 break;
106 case MultiviewOption::InstancedMultiviewVertexShader:
107 name += "_instanced_multiview_vertex_shader";
108 break;
109 case MultiviewOption::InstancedMultiviewGeometryShader:
110 name += "_instanced_multiview_geometry_shader";
111 break;
112 default:
113 name += "_error";
114 break;
115 }
116 std::string ext;
117 switch (multiviewExtension)
118 {
119 case multiview:
120 ext = "GL_OVR_multiview";
121 break;
122 case multiview2:
123 ext = "GL_OVR_multiview2";
124 break;
125 default:
126 ext = "extension_error";
127 break;
128 }
129 name += "_" + ext;
130 name += "_" + ToString(numViews) + "_views";
131 return name;
132 }
133
134 MultiviewOption multiviewOption;
135 int numViews;
136 angle::ExtensionName multiviewExtension;
137 };
138
operator <<(std::ostream & os,const MultiviewPerfParams & params)139 std::ostream &operator<<(std::ostream &os, const MultiviewPerfParams ¶ms)
140 {
141 os << params.backendAndStory().substr(1);
142 return os;
143 }
144
145 class MultiviewBenchmark : public ANGLERenderTest,
146 public ::testing::WithParamInterface<MultiviewPerfParams>
147 {
148 public:
MultiviewBenchmark(const std::string & testName)149 MultiviewBenchmark(const std::string &testName)
150 : ANGLERenderTest(testName, GetParam()), mProgram(0)
151 {
152 switch (GetParam().multiviewExtension)
153 {
154 case multiview:
155 addExtensionPrerequisite("GL_OVR_multiview");
156 break;
157 case multiview2:
158 addExtensionPrerequisite("GL_OVR_multiview2");
159 break;
160 default:
161 // Unknown extension.
162 break;
163 }
164 }
165
~MultiviewBenchmark()166 virtual ~MultiviewBenchmark()
167 {
168 if (mProgram != 0)
169 {
170 glDeleteProgram(mProgram);
171 }
172 }
173
174 void initializeBenchmark() override;
175 void drawBenchmark() final;
176
177 protected:
178 virtual void renderScene() = 0;
179
createProgram(const char * vs,const char * fs)180 void createProgram(const char *vs, const char *fs)
181 {
182 mProgram = CompileProgram(vs, fs);
183 if (mProgram == 0)
184 {
185 FAIL() << "shader compilation failed.";
186 }
187 glUseProgram(mProgram);
188 ASSERT_GL_NO_ERROR();
189 }
190
191 GLuint mProgram;
192 GLVertexArray mVAO;
193 GLBuffer mVBO;
194
195 private:
196 GLFramebuffer mFramebuffer;
197 GLTexture mColorTexture;
198 GLTexture mDepthTexture;
199 };
200
201 class MultiviewCPUBoundBenchmark : public MultiviewBenchmark
202 {
203 public:
MultiviewCPUBoundBenchmark()204 MultiviewCPUBoundBenchmark() : MultiviewBenchmark("MultiviewCPUBoundBenchmark") {}
205
206 void initializeBenchmark() override;
207
208 protected:
209 void renderScene() override;
210 };
211
212 class MultiviewGPUBoundBenchmark : public MultiviewBenchmark
213 {
214 public:
MultiviewGPUBoundBenchmark()215 MultiviewGPUBoundBenchmark() : MultiviewBenchmark("MultiviewGPUBoundBenchmark") {}
216
217 void initializeBenchmark() override;
218
219 protected:
220 void renderScene() override;
221 };
222
initializeBenchmark()223 void MultiviewBenchmark::initializeBenchmark()
224 {
225 const MultiviewPerfParams *params = static_cast<const MultiviewPerfParams *>(&mTestParams);
226
227 switch (params->multiviewOption)
228 {
229 case MultiviewOption::NoAcceleration:
230 // No acceleration texture arrays
231 glBindTexture(GL_TEXTURE_2D, mColorTexture);
232 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, params->windowWidth, params->windowHeight, 0,
233 GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
234
235 glBindTexture(GL_TEXTURE_2D, mDepthTexture);
236 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, params->windowWidth,
237 params->windowHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
238
239 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
240 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
241 mColorTexture, 0);
242 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
243 mDepthTexture, 0);
244 break;
245 case MultiviewOption::InstancedMultiviewVertexShader:
246 case MultiviewOption::InstancedMultiviewGeometryShader:
247 {
248 // Multiview texture arrays
249 glBindTexture(GL_TEXTURE_2D_ARRAY, mColorTexture);
250 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, params->windowWidth,
251 params->windowHeight, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
252
253 glBindTexture(GL_TEXTURE_2D_ARRAY, mDepthTexture);
254 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT32F, params->windowWidth,
255 params->windowHeight, 2, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
256
257 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
258 glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mColorTexture, 0,
259 0, params->numViews);
260 glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, mDepthTexture, 0,
261 0, params->numViews);
262 break;
263 }
264 case MultiviewOption::Unspecified:
265 // implementation error.
266 break;
267 }
268
269 GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0};
270 glDrawBuffers(1, DrawBuffers);
271
272 ASSERT_GL_NO_ERROR();
273 }
274
drawBenchmark()275 void MultiviewBenchmark::drawBenchmark()
276 {
277 const MultiviewPerfParams *params = static_cast<const MultiviewPerfParams *>(&mTestParams);
278 const int viewWidth = params->windowWidth / params->numViews;
279 const int viewHeight = params->windowHeight;
280
281 switch (params->multiviewOption)
282 {
283 case MultiviewOption::NoAcceleration:
284 glEnable(GL_SCISSOR_TEST);
285 // Iterate over each view and render the scene.
286 for (int i = 0; i < params->numViews; ++i)
287 {
288 glViewport(viewWidth * i, 0, viewWidth, viewHeight);
289 glScissor(viewWidth * i, 0, viewWidth, viewHeight);
290 renderScene();
291 }
292 break;
293 case MultiviewOption::InstancedMultiviewVertexShader:
294 case MultiviewOption::InstancedMultiviewGeometryShader:
295 glViewport(0, 0, viewWidth, viewHeight);
296 glScissor(0, 0, viewWidth, viewHeight);
297 renderScene();
298 break;
299 case MultiviewOption::Unspecified:
300 // implementation error.
301 break;
302 }
303
304 ASSERT_GL_NO_ERROR();
305 }
306
initializeBenchmark()307 void MultiviewCPUBoundBenchmark::initializeBenchmark()
308 {
309 MultiviewBenchmark::initializeBenchmark();
310
311 const MultiviewPerfParams *params = static_cast<const MultiviewPerfParams *>(&mTestParams);
312 const bool usesMultiview = (params->multiviewOption != MultiviewOption::NoAcceleration);
313
314 const std::string vs = "#version 300 es\n" +
315 GetShaderExtensionHeader(usesMultiview, params->numViews,
316 GL_VERTEX_SHADER, params->multiviewExtension) +
317 "layout(location=0) in vec4 vPosition;\n"
318 "uniform vec2 uOffset;\n"
319 "void main()\n"
320 "{\n"
321 " vec4 v = vPosition;\n"
322 " v.xy += uOffset;\n"
323 " gl_Position = v;\n"
324 "}\n";
325
326 const std::string fs =
327 "#version 300 es\n" +
328 GetShaderExtensionHeader(usesMultiview, params->numViews, GL_FRAGMENT_SHADER,
329 params->multiviewExtension) +
330 "precision mediump float;\n"
331 "out vec4 col;\n"
332 "uniform float uColor;\n"
333 "void main()\n"
334 "{\n"
335 " col = vec4(1.);\n"
336 "}\n";
337
338 createProgram(vs.c_str(), fs.c_str());
339
340 const float viewWidth = static_cast<float>(params->windowWidth / params->numViews);
341 const float viewHeight = static_cast<float>(params->windowHeight);
342 const float quadWidth = 2.f / viewWidth;
343 const float quadHeight = 2.f / viewHeight;
344 Vector4 vertices[6] = {Vector4(.0f, .0f, .0f, 1.f),
345 Vector4(quadWidth, .0f, .0f, 1.f),
346 Vector4(quadWidth, quadHeight, 0.f, 1.f),
347 Vector4(.0f, .0f, 0.f, 1.f),
348 Vector4(quadWidth, quadHeight, .0f, 1.f),
349 Vector4(.0f, quadHeight, .0f, 1.f)};
350
351 glBindVertexArray(mVAO);
352
353 glBindBuffer(GL_ARRAY_BUFFER, mVBO);
354 glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(Vector4), vertices, GL_STATIC_DRAW);
355
356 const GLint posLoc = glGetAttribLocation(mProgram, "vPosition");
357 glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, 0);
358 glEnableVertexAttribArray(posLoc);
359
360 // Render once to guarantee that the program is compiled and linked.
361 drawBenchmark();
362
363 ASSERT_GL_NO_ERROR();
364 }
365
renderScene()366 void MultiviewCPUBoundBenchmark::renderScene()
367 {
368 glClearColor(0, 0, 0, 0);
369 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
370 glUseProgram(mProgram);
371
372 glBindVertexArray(mVAO);
373
374 const MultiviewPerfParams *params = static_cast<const MultiviewPerfParams *>(&mTestParams);
375 const int viewWidth = params->windowWidth / params->numViews;
376 const int viewHeight = params->windowHeight;
377
378 for (int w = 0; w < viewWidth; ++w)
379 {
380 for (int h = 0; h < viewHeight; ++h)
381 {
382 const float wf = static_cast<float>(w) / viewWidth;
383 const float wh = static_cast<float>(h) / viewHeight;
384 glUniform2f(glGetUniformLocation(mProgram, "uOffset"), 2.f * wf - 1.f, 2.f * wh - 1.f);
385 glUniform1f(glGetUniformLocation(mProgram, "uColor"), wf);
386 glDrawArrays(GL_TRIANGLES, 0, 6);
387 }
388 }
389 }
390
initializeBenchmark()391 void MultiviewGPUBoundBenchmark::initializeBenchmark()
392 {
393 MultiviewBenchmark::initializeBenchmark();
394
395 const MultiviewPerfParams *params = static_cast<const MultiviewPerfParams *>(&mTestParams);
396 const bool usesMultiview = (params->multiviewOption != MultiviewOption::NoAcceleration);
397
398 const std::string &vs = "#version 300 es\n" +
399 GetShaderExtensionHeader(usesMultiview, params->numViews,
400 GL_VERTEX_SHADER, params->multiviewExtension) +
401 "layout(location=0) in vec4 vPosition;\n"
402 "layout(location=1) in vec4 vert_Col0;\n"
403 "layout(location=2) in vec4 vert_Col1;\n"
404 "layout(location=3) in vec4 vert_Col2;\n"
405 "layout(location=4) in vec4 vert_Col3;\n"
406 "layout(location=5) in vec4 vert_Col4;\n"
407 "layout(location=6) in vec4 vert_Col5;\n"
408 "out vec4 frag_Col0;\n"
409 "out vec4 frag_Col1;\n"
410 "out vec4 frag_Col2;\n"
411 "out vec4 frag_Col3;\n"
412 "out vec4 frag_Col4;\n"
413 "out vec4 frag_Col5;\n"
414 "void main()\n"
415 "{\n"
416 " frag_Col0 = vert_Col0;\n"
417 " frag_Col1 = vert_Col1;\n"
418 " frag_Col2 = vert_Col2;\n"
419 " frag_Col3 = vert_Col3;\n"
420 " frag_Col4 = vert_Col4;\n"
421 " frag_Col5 = vert_Col5;\n"
422 " gl_Position = vPosition;\n"
423 "}\n";
424
425 const std::string &fs =
426 "#version 300 es\n" +
427 GetShaderExtensionHeader(usesMultiview, params->numViews, GL_FRAGMENT_SHADER,
428 params->multiviewExtension) +
429 "precision mediump float;\n"
430 "in vec4 frag_Col0;\n"
431 "in vec4 frag_Col1;\n"
432 "in vec4 frag_Col2;\n"
433 "in vec4 frag_Col3;\n"
434 "in vec4 frag_Col4;\n"
435 "in vec4 frag_Col5;\n"
436 "out vec4 col;\n"
437 "void main()\n"
438 "{\n"
439 " col += frag_Col0;\n"
440 " col += frag_Col1;\n"
441 " col += frag_Col2;\n"
442 " col += frag_Col3;\n"
443 " col += frag_Col4;\n"
444 " col += frag_Col5;\n"
445 "}\n";
446
447 createProgram(vs.c_str(), fs.c_str());
448 ASSERT_GL_NO_ERROR();
449
450 // Generate a vertex buffer of triangulated quads so that we have one quad per pixel.
451 const int viewWidth = params->windowWidth / params->numViews;
452 const int viewHeight = params->windowHeight;
453 const float quadWidth = 2.f / static_cast<float>(viewWidth);
454 const float quadHeight = 2.f / static_cast<float>(viewHeight);
455 const int kNumQuads = viewWidth * viewHeight;
456 const int kNumVerticesPerQuad = 6;
457 std::vector<Vertex> vertexData(kNumQuads * kNumVerticesPerQuad);
458 for (int h = 0; h < viewHeight; ++h)
459 {
460 for (int w = 0; w < viewWidth; ++w)
461 {
462 float wf = static_cast<float>(w) / viewWidth;
463 float hf = static_cast<float>(h) / viewHeight;
464
465 size_t index = static_cast<size_t>(h * viewWidth + w) * 6u;
466
467 auto &v0 = vertexData[index];
468 v0.position = Vector4(2.f * wf - 1.f, 2.f * hf - 1.f, .0f, 1.f);
469 memset(v0.colorAttributeData, 0, sizeof(v0.colorAttributeData));
470
471 auto &v1 = vertexData[index + 1];
472 v1.position = Vector4(v0.position.x() + quadWidth, v0.position.y(), .0f, 1.f);
473 memset(v1.colorAttributeData, 0, sizeof(v1.colorAttributeData));
474
475 auto &v2 = vertexData[index + 2];
476 v2.position = Vector4(v1.position.x(), v1.position.y() + quadHeight, .0f, 1.f);
477 memset(v2.colorAttributeData, 0, sizeof(v2.colorAttributeData));
478
479 auto &v3 = vertexData[index + 3];
480 v3.position = v0.position;
481 memset(v3.colorAttributeData, 0, sizeof(v3.colorAttributeData));
482
483 auto &v4 = vertexData[index + 4];
484 v4.position = v2.position;
485 memset(v4.colorAttributeData, 0, sizeof(v4.colorAttributeData));
486
487 auto &v5 = vertexData[index + 5];
488 v5.position = Vector4(v0.position.x(), v0.position.y() + quadHeight, .0f, 1.f);
489 memset(v5.colorAttributeData, 0, sizeof(v5.colorAttributeData));
490 }
491 }
492
493 glBindVertexArray(mVAO);
494
495 glBindBuffer(GL_ARRAY_BUFFER, mVBO);
496 glBufferData(GL_ARRAY_BUFFER, vertexData.size() * sizeof(Vertex), vertexData.data(),
497 GL_STATIC_DRAW);
498
499 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
500 glEnableVertexAttribArray(0);
501
502 for (unsigned int i = 0u; i < 6u; ++i)
503 {
504 size_t offset = sizeof(Vector4) * (i + 1u);
505 glVertexAttribPointer(i + 1, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex),
506 reinterpret_cast<const void *>(offset));
507 glEnableVertexAttribArray(i + 1);
508 }
509
510 // Render once to guarantee that the program is compiled and linked.
511 drawBenchmark();
512 }
513
renderScene()514 void MultiviewGPUBoundBenchmark::renderScene()
515 {
516 glClearColor(0, 0, 0, 0);
517 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
518 glUseProgram(mProgram);
519
520 glBindVertexArray(mVAO);
521
522 const MultiviewPerfParams *params = static_cast<const MultiviewPerfParams *>(&mTestParams);
523 const int viewWidth = params->windowWidth / params->numViews;
524 const int viewHeight = params->windowHeight;
525 glDrawArrays(GL_TRIANGLES, 0, viewWidth * viewHeight * 6);
526 }
527
528 namespace
529 {
SmallWorkload()530 MultiviewPerfWorkload SmallWorkload()
531 {
532 return MultiviewPerfWorkload(64, 64);
533 }
534
BigWorkload()535 MultiviewPerfWorkload BigWorkload()
536 {
537 return MultiviewPerfWorkload(1024, 768);
538 }
539
NoAcceleration(const EGLPlatformParameters & eglParameters,const MultiviewPerfWorkload & workload,ExtensionName multiviewExtensionIn)540 MultiviewPerfParams NoAcceleration(const EGLPlatformParameters &eglParameters,
541 const MultiviewPerfWorkload &workload,
542 ExtensionName multiviewExtensionIn)
543 {
544 return MultiviewPerfParams(eglParameters, workload, MultiviewOption::NoAcceleration,
545 multiviewExtensionIn);
546 }
547
SelectViewInGeometryShader(const MultiviewPerfWorkload & workload,ExtensionName multiviewExtensionIn)548 MultiviewPerfParams SelectViewInGeometryShader(const MultiviewPerfWorkload &workload,
549 ExtensionName multiviewExtensionIn)
550 {
551 return MultiviewPerfParams(egl_platform::D3D11(), workload,
552 MultiviewOption::InstancedMultiviewGeometryShader,
553 multiviewExtensionIn);
554 }
555
SelectViewInVertexShader(const EGLPlatformParameters & eglParameters,const MultiviewPerfWorkload & workload,ExtensionName multiviewExtensionIn)556 MultiviewPerfParams SelectViewInVertexShader(const EGLPlatformParameters &eglParameters,
557 const MultiviewPerfWorkload &workload,
558 ExtensionName multiviewExtensionIn)
559 {
560 return MultiviewPerfParams(eglParameters, workload,
561 MultiviewOption::InstancedMultiviewVertexShader,
562 multiviewExtensionIn);
563 }
564 } // namespace
565
TEST_P(MultiviewCPUBoundBenchmark,Run)566 TEST_P(MultiviewCPUBoundBenchmark, Run)
567 {
568 run();
569 }
570
571 ANGLE_INSTANTIATE_TEST(
572 MultiviewCPUBoundBenchmark,
573 NoAcceleration(egl_platform::OPENGL_OR_GLES(), SmallWorkload(), ExtensionName::multiview),
574 NoAcceleration(egl_platform::D3D11(), SmallWorkload(), ExtensionName::multiview),
575 SelectViewInGeometryShader(SmallWorkload(), ExtensionName::multiview),
576 SelectViewInVertexShader(egl_platform::OPENGL_OR_GLES(),
577 SmallWorkload(),
578 ExtensionName::multiview),
579 SelectViewInVertexShader(egl_platform::D3D11(), SmallWorkload(), ExtensionName::multiview),
580 NoAcceleration(egl_platform::OPENGL_OR_GLES(), SmallWorkload(), ExtensionName::multiview2),
581 NoAcceleration(egl_platform::D3D11(), SmallWorkload(), ExtensionName::multiview2),
582 SelectViewInGeometryShader(SmallWorkload(), ExtensionName::multiview2),
583 SelectViewInVertexShader(egl_platform::OPENGL_OR_GLES(),
584 SmallWorkload(),
585 ExtensionName::multiview2),
586 SelectViewInVertexShader(egl_platform::D3D11(), SmallWorkload(), ExtensionName::multiview2));
587
TEST_P(MultiviewGPUBoundBenchmark,Run)588 TEST_P(MultiviewGPUBoundBenchmark, Run)
589 {
590 run();
591 }
592
593 ANGLE_INSTANTIATE_TEST(
594 MultiviewGPUBoundBenchmark,
595 NoAcceleration(egl_platform::OPENGL_OR_GLES(), BigWorkload(), ExtensionName::multiview),
596 NoAcceleration(egl_platform::D3D11(), BigWorkload(), ExtensionName::multiview),
597 SelectViewInGeometryShader(BigWorkload(), ExtensionName::multiview),
598 SelectViewInVertexShader(egl_platform::OPENGL_OR_GLES(),
599 BigWorkload(),
600 ExtensionName::multiview),
601 SelectViewInVertexShader(egl_platform::D3D11(), BigWorkload(), ExtensionName::multiview),
602 NoAcceleration(egl_platform::OPENGL_OR_GLES(), BigWorkload(), ExtensionName::multiview2),
603 NoAcceleration(egl_platform::D3D11(), BigWorkload(), ExtensionName::multiview2),
604 SelectViewInGeometryShader(BigWorkload(), ExtensionName::multiview2),
605 SelectViewInVertexShader(egl_platform::OPENGL_OR_GLES(),
606 BigWorkload(),
607 ExtensionName::multiview2),
608 SelectViewInVertexShader(egl_platform::D3D11(), BigWorkload(), ExtensionName::multiview2));
609
610 } // anonymous namespace
611