Path: blob/main_old/src/tests/perf_tests/MultiviewPerf.cpp
1693 views
//1// Copyright 2017 The ANGLE Project Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file.4//5// MultiviewPerfTest:6// Performance tests for multiview rendering.7// - MultiviewCPUBoundBenchmark issues many draw calls and state changes to stress the CPU.8// - MultiviewGPUBoundBenchmark draws half a million quads with multiple attributes per vertex in9// order to stress the GPU's memory system.10//1112#include "ANGLEPerfTest.h"13#include "common/vector_utils.h"14#include "platform/FeaturesD3D.h"15#include "test_utils/MultiviewTest.h"16#include "test_utils/gl_raii.h"17#include "util/shader_utils.h"1819#include <string.h>2021using namespace angle;2223namespace24{2526std::string GetShaderExtensionHeader(bool usesMultiview,27int numViews,28GLenum shaderType,29ExtensionName multiviewExtension)30{31if (!usesMultiview)32{33return "";34}3536std::string ext;37switch (multiviewExtension)38{39case multiview:40ext = "GL_OVR_multiview";41break;42case multiview2:43ext = "GL_OVR_multiview2";44break;45default:46ext = "extension_error";47}4849if (shaderType == GL_VERTEX_SHADER)50{51return "#extension " + ext + " : require\nlayout(num_views = " + ToString(numViews) +52") in;\n";53}54return "#extension " + ext + " : require\n";55}5657struct Vertex58{59Vector4 position;60Vector4 colorAttributeData[6];61};6263enum class MultiviewOption64{65NoAcceleration,66InstancedMultiviewVertexShader,67InstancedMultiviewGeometryShader,6869Unspecified70};7172using MultiviewPerfWorkload = std::pair<int, int>;7374struct MultiviewPerfParams final : public RenderTestParams75{76MultiviewPerfParams(const EGLPlatformParameters &platformParametersIn,77const MultiviewPerfWorkload &workloadIn,78MultiviewOption multiviewOptionIn,79ExtensionName multiviewExtensionIn)80{81iterationsPerStep = 1;82majorVersion = 3;83minorVersion = 0;84eglParameters = platformParametersIn;85windowWidth = workloadIn.first;86windowHeight = workloadIn.second;87multiviewOption = multiviewOptionIn;88numViews = 2;89multiviewExtension = multiviewExtensionIn;90}9192std::string story() const override93{94std::string name = RenderTestParams::story();95switch (multiviewOption)96{97case MultiviewOption::NoAcceleration:98name += "_no_acc";99break;100case MultiviewOption::InstancedMultiviewVertexShader:101name += "_instanced_multiview_vertex_shader";102break;103case MultiviewOption::InstancedMultiviewGeometryShader:104name += "_instanced_multiview_geometry_shader";105break;106default:107name += "_error";108break;109}110std::string ext;111switch (multiviewExtension)112{113case multiview:114ext = "GL_OVR_multiview";115break;116case multiview2:117ext = "GL_OVR_multiview2";118break;119default:120ext = "extension_error";121break;122}123name += "_" + ext;124name += "_" + ToString(numViews) + "_views";125return name;126}127128MultiviewOption multiviewOption;129int numViews;130angle::ExtensionName multiviewExtension;131};132133std::ostream &operator<<(std::ostream &os, const MultiviewPerfParams ¶ms)134{135os << params.backendAndStory().substr(1);136return os;137}138139class MultiviewBenchmark : public ANGLERenderTest,140public ::testing::WithParamInterface<MultiviewPerfParams>141{142public:143MultiviewBenchmark(const std::string &testName)144: ANGLERenderTest(testName, GetParam()), mProgram(0)145{146switch (GetParam().multiviewExtension)147{148case multiview:149addExtensionPrerequisite("GL_OVR_multiview");150break;151case multiview2:152addExtensionPrerequisite("GL_OVR_multiview2");153break;154default:155// Unknown extension.156break;157}158}159160virtual ~MultiviewBenchmark()161{162if (mProgram != 0)163{164glDeleteProgram(mProgram);165}166}167168void initializeBenchmark() override;169void drawBenchmark() final;170171void overrideWorkaroundsD3D(FeaturesD3D *features) override172{173features->overrideFeatures(174{"select_view_in_geometry_shader"},175GetParam().multiviewOption == MultiviewOption::InstancedMultiviewGeometryShader);176}177178protected:179virtual void renderScene() = 0;180181void createProgram(const char *vs, const char *fs)182{183mProgram = CompileProgram(vs, fs);184if (mProgram == 0)185{186FAIL() << "shader compilation failed.";187}188glUseProgram(mProgram);189ASSERT_GL_NO_ERROR();190}191192GLuint mProgram;193GLVertexArray mVAO;194GLBuffer mVBO;195196private:197GLFramebuffer mFramebuffer;198GLTexture mColorTexture;199GLTexture mDepthTexture;200};201202class MultiviewCPUBoundBenchmark : public MultiviewBenchmark203{204public:205MultiviewCPUBoundBenchmark() : MultiviewBenchmark("MultiviewCPUBoundBenchmark") {}206207void initializeBenchmark() override;208209protected:210void renderScene() override;211};212213class MultiviewGPUBoundBenchmark : public MultiviewBenchmark214{215public:216MultiviewGPUBoundBenchmark() : MultiviewBenchmark("MultiviewGPUBoundBenchmark") {}217218void initializeBenchmark() override;219220protected:221void renderScene() override;222};223224void MultiviewBenchmark::initializeBenchmark()225{226const MultiviewPerfParams *params = static_cast<const MultiviewPerfParams *>(&mTestParams);227228switch (params->multiviewOption)229{230case MultiviewOption::NoAcceleration:231// No acceleration texture arrays232glBindTexture(GL_TEXTURE_2D, mColorTexture);233glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, params->windowWidth, params->windowHeight, 0,234GL_RGBA, GL_UNSIGNED_BYTE, nullptr);235236glBindTexture(GL_TEXTURE_2D, mDepthTexture);237glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, params->windowWidth,238params->windowHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);239240glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);241glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,242mColorTexture, 0);243glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,244mDepthTexture, 0);245break;246case MultiviewOption::InstancedMultiviewVertexShader:247case MultiviewOption::InstancedMultiviewGeometryShader:248{249// Multiview texture arrays250glBindTexture(GL_TEXTURE_2D_ARRAY, mColorTexture);251glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, params->windowWidth,252params->windowHeight, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);253254glBindTexture(GL_TEXTURE_2D_ARRAY, mDepthTexture);255glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT32F, params->windowWidth,256params->windowHeight, 2, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);257258glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);259glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mColorTexture, 0,2600, params->numViews);261glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, mDepthTexture, 0,2620, params->numViews);263break;264}265case MultiviewOption::Unspecified:266// implementation error.267break;268}269270GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0};271glDrawBuffers(1, DrawBuffers);272273ASSERT_GL_NO_ERROR();274}275276void MultiviewBenchmark::drawBenchmark()277{278const MultiviewPerfParams *params = static_cast<const MultiviewPerfParams *>(&mTestParams);279const int viewWidth = params->windowWidth / params->numViews;280const int viewHeight = params->windowHeight;281282switch (params->multiviewOption)283{284case MultiviewOption::NoAcceleration:285glEnable(GL_SCISSOR_TEST);286// Iterate over each view and render the scene.287for (int i = 0; i < params->numViews; ++i)288{289glViewport(viewWidth * i, 0, viewWidth, viewHeight);290glScissor(viewWidth * i, 0, viewWidth, viewHeight);291renderScene();292}293break;294case MultiviewOption::InstancedMultiviewVertexShader:295case MultiviewOption::InstancedMultiviewGeometryShader:296glViewport(0, 0, viewWidth, viewHeight);297glScissor(0, 0, viewWidth, viewHeight);298renderScene();299break;300case MultiviewOption::Unspecified:301// implementation error.302break;303}304305ASSERT_GL_NO_ERROR();306}307308void MultiviewCPUBoundBenchmark::initializeBenchmark()309{310MultiviewBenchmark::initializeBenchmark();311312const MultiviewPerfParams *params = static_cast<const MultiviewPerfParams *>(&mTestParams);313const bool usesMultiview = (params->multiviewOption != MultiviewOption::NoAcceleration);314315const std::string vs = "#version 300 es\n" +316GetShaderExtensionHeader(usesMultiview, params->numViews,317GL_VERTEX_SHADER, params->multiviewExtension) +318"layout(location=0) in vec4 vPosition;\n"319"uniform vec2 uOffset;\n"320"void main()\n"321"{\n"322" vec4 v = vPosition;\n"323" v.xy += uOffset;\n"324" gl_Position = v;\n"325"}\n";326327const std::string fs =328"#version 300 es\n" +329GetShaderExtensionHeader(usesMultiview, params->numViews, GL_FRAGMENT_SHADER,330params->multiviewExtension) +331"precision mediump float;\n"332"out vec4 col;\n"333"uniform float uColor;\n"334"void main()\n"335"{\n"336" col = vec4(1.);\n"337"}\n";338339createProgram(vs.c_str(), fs.c_str());340341const float viewWidth = static_cast<float>(params->windowWidth / params->numViews);342const float viewHeight = static_cast<float>(params->windowHeight);343const float quadWidth = 2.f / viewWidth;344const float quadHeight = 2.f / viewHeight;345Vector4 vertices[6] = {Vector4(.0f, .0f, .0f, 1.f),346Vector4(quadWidth, .0f, .0f, 1.f),347Vector4(quadWidth, quadHeight, 0.f, 1.f),348Vector4(.0f, .0f, 0.f, 1.f),349Vector4(quadWidth, quadHeight, .0f, 1.f),350Vector4(.0f, quadHeight, .0f, 1.f)};351352glBindVertexArray(mVAO);353354glBindBuffer(GL_ARRAY_BUFFER, mVBO);355glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(Vector4), vertices, GL_STATIC_DRAW);356357const GLint posLoc = glGetAttribLocation(mProgram, "vPosition");358glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, 0);359glEnableVertexAttribArray(posLoc);360361// Render once to guarantee that the program is compiled and linked.362drawBenchmark();363364ASSERT_GL_NO_ERROR();365}366367void MultiviewCPUBoundBenchmark::renderScene()368{369glClearColor(0, 0, 0, 0);370glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);371glUseProgram(mProgram);372373glBindVertexArray(mVAO);374375const MultiviewPerfParams *params = static_cast<const MultiviewPerfParams *>(&mTestParams);376const int viewWidth = params->windowWidth / params->numViews;377const int viewHeight = params->windowHeight;378379for (int w = 0; w < viewWidth; ++w)380{381for (int h = 0; h < viewHeight; ++h)382{383const float wf = static_cast<float>(w) / viewWidth;384const float wh = static_cast<float>(h) / viewHeight;385glUniform2f(glGetUniformLocation(mProgram, "uOffset"), 2.f * wf - 1.f, 2.f * wh - 1.f);386glUniform1f(glGetUniformLocation(mProgram, "uColor"), wf);387glDrawArrays(GL_TRIANGLES, 0, 6);388}389}390}391392void MultiviewGPUBoundBenchmark::initializeBenchmark()393{394MultiviewBenchmark::initializeBenchmark();395396const MultiviewPerfParams *params = static_cast<const MultiviewPerfParams *>(&mTestParams);397const bool usesMultiview = (params->multiviewOption != MultiviewOption::NoAcceleration);398399const std::string &vs = "#version 300 es\n" +400GetShaderExtensionHeader(usesMultiview, params->numViews,401GL_VERTEX_SHADER, params->multiviewExtension) +402"layout(location=0) in vec4 vPosition;\n"403"layout(location=1) in vec4 vert_Col0;\n"404"layout(location=2) in vec4 vert_Col1;\n"405"layout(location=3) in vec4 vert_Col2;\n"406"layout(location=4) in vec4 vert_Col3;\n"407"layout(location=5) in vec4 vert_Col4;\n"408"layout(location=6) in vec4 vert_Col5;\n"409"out vec4 frag_Col0;\n"410"out vec4 frag_Col1;\n"411"out vec4 frag_Col2;\n"412"out vec4 frag_Col3;\n"413"out vec4 frag_Col4;\n"414"out vec4 frag_Col5;\n"415"void main()\n"416"{\n"417" frag_Col0 = vert_Col0;\n"418" frag_Col1 = vert_Col1;\n"419" frag_Col2 = vert_Col2;\n"420" frag_Col3 = vert_Col3;\n"421" frag_Col4 = vert_Col4;\n"422" frag_Col5 = vert_Col5;\n"423" gl_Position = vPosition;\n"424"}\n";425426const std::string &fs =427"#version 300 es\n" +428GetShaderExtensionHeader(usesMultiview, params->numViews, GL_FRAGMENT_SHADER,429params->multiviewExtension) +430"precision mediump float;\n"431"in vec4 frag_Col0;\n"432"in vec4 frag_Col1;\n"433"in vec4 frag_Col2;\n"434"in vec4 frag_Col3;\n"435"in vec4 frag_Col4;\n"436"in vec4 frag_Col5;\n"437"out vec4 col;\n"438"void main()\n"439"{\n"440" col += frag_Col0;\n"441" col += frag_Col1;\n"442" col += frag_Col2;\n"443" col += frag_Col3;\n"444" col += frag_Col4;\n"445" col += frag_Col5;\n"446"}\n";447448createProgram(vs.c_str(), fs.c_str());449ASSERT_GL_NO_ERROR();450451// Generate a vertex buffer of triangulated quads so that we have one quad per pixel.452const int viewWidth = params->windowWidth / params->numViews;453const int viewHeight = params->windowHeight;454const float quadWidth = 2.f / static_cast<float>(viewWidth);455const float quadHeight = 2.f / static_cast<float>(viewHeight);456const int kNumQuads = viewWidth * viewHeight;457const int kNumVerticesPerQuad = 6;458std::vector<Vertex> vertexData(kNumQuads * kNumVerticesPerQuad);459for (int h = 0; h < viewHeight; ++h)460{461for (int w = 0; w < viewWidth; ++w)462{463float wf = static_cast<float>(w) / viewWidth;464float hf = static_cast<float>(h) / viewHeight;465466size_t index = static_cast<size_t>(h * viewWidth + w) * 6u;467468auto &v0 = vertexData[index];469v0.position = Vector4(2.f * wf - 1.f, 2.f * hf - 1.f, .0f, 1.f);470memset(v0.colorAttributeData, 0, sizeof(v0.colorAttributeData));471472auto &v1 = vertexData[index + 1];473v1.position = Vector4(v0.position.x() + quadWidth, v0.position.y(), .0f, 1.f);474memset(v1.colorAttributeData, 0, sizeof(v1.colorAttributeData));475476auto &v2 = vertexData[index + 2];477v2.position = Vector4(v1.position.x(), v1.position.y() + quadHeight, .0f, 1.f);478memset(v2.colorAttributeData, 0, sizeof(v2.colorAttributeData));479480auto &v3 = vertexData[index + 3];481v3.position = v0.position;482memset(v3.colorAttributeData, 0, sizeof(v3.colorAttributeData));483484auto &v4 = vertexData[index + 4];485v4.position = v2.position;486memset(v4.colorAttributeData, 0, sizeof(v4.colorAttributeData));487488auto &v5 = vertexData[index + 5];489v5.position = Vector4(v0.position.x(), v0.position.y() + quadHeight, .0f, 1.f);490memset(v5.colorAttributeData, 0, sizeof(v5.colorAttributeData));491}492}493494glBindVertexArray(mVAO);495496glBindBuffer(GL_ARRAY_BUFFER, mVBO);497glBufferData(GL_ARRAY_BUFFER, vertexData.size() * sizeof(Vertex), vertexData.data(),498GL_STATIC_DRAW);499500glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);501glEnableVertexAttribArray(0);502503for (unsigned int i = 0u; i < 6u; ++i)504{505size_t offset = sizeof(Vector4) * (i + 1u);506glVertexAttribPointer(i + 1, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex),507reinterpret_cast<const void *>(offset));508glEnableVertexAttribArray(i + 1);509}510511// Render once to guarantee that the program is compiled and linked.512drawBenchmark();513}514515void MultiviewGPUBoundBenchmark::renderScene()516{517glClearColor(0, 0, 0, 0);518glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);519glUseProgram(mProgram);520521glBindVertexArray(mVAO);522523const MultiviewPerfParams *params = static_cast<const MultiviewPerfParams *>(&mTestParams);524const int viewWidth = params->windowWidth / params->numViews;525const int viewHeight = params->windowHeight;526glDrawArrays(GL_TRIANGLES, 0, viewWidth * viewHeight * 6);527}528529namespace530{531MultiviewPerfWorkload SmallWorkload()532{533return MultiviewPerfWorkload(64, 64);534}535536MultiviewPerfWorkload BigWorkload()537{538return MultiviewPerfWorkload(1024, 768);539}540541MultiviewPerfParams NoAcceleration(const EGLPlatformParameters &eglParameters,542const MultiviewPerfWorkload &workload,543ExtensionName multiviewExtensionIn)544{545return MultiviewPerfParams(eglParameters, workload, MultiviewOption::NoAcceleration,546multiviewExtensionIn);547}548549MultiviewPerfParams SelectViewInGeometryShader(const MultiviewPerfWorkload &workload,550ExtensionName multiviewExtensionIn)551{552return MultiviewPerfParams(egl_platform::D3D11(), workload,553MultiviewOption::InstancedMultiviewGeometryShader,554multiviewExtensionIn);555}556557MultiviewPerfParams SelectViewInVertexShader(const EGLPlatformParameters &eglParameters,558const MultiviewPerfWorkload &workload,559ExtensionName multiviewExtensionIn)560{561return MultiviewPerfParams(eglParameters, workload,562MultiviewOption::InstancedMultiviewVertexShader,563multiviewExtensionIn);564}565} // namespace566567TEST_P(MultiviewCPUBoundBenchmark, Run)568{569run();570}571572ANGLE_INSTANTIATE_TEST(573MultiviewCPUBoundBenchmark,574NoAcceleration(egl_platform::OPENGL_OR_GLES(), SmallWorkload(), ExtensionName::multiview),575NoAcceleration(egl_platform::D3D11(), SmallWorkload(), ExtensionName::multiview),576SelectViewInGeometryShader(SmallWorkload(), ExtensionName::multiview),577SelectViewInVertexShader(egl_platform::OPENGL_OR_GLES(),578SmallWorkload(),579ExtensionName::multiview),580SelectViewInVertexShader(egl_platform::D3D11(), SmallWorkload(), ExtensionName::multiview),581NoAcceleration(egl_platform::OPENGL_OR_GLES(), SmallWorkload(), ExtensionName::multiview2),582NoAcceleration(egl_platform::D3D11(), SmallWorkload(), ExtensionName::multiview2),583SelectViewInGeometryShader(SmallWorkload(), ExtensionName::multiview2),584SelectViewInVertexShader(egl_platform::OPENGL_OR_GLES(),585SmallWorkload(),586ExtensionName::multiview2),587SelectViewInVertexShader(egl_platform::D3D11(), SmallWorkload(), ExtensionName::multiview2));588589TEST_P(MultiviewGPUBoundBenchmark, Run)590{591run();592}593594ANGLE_INSTANTIATE_TEST(595MultiviewGPUBoundBenchmark,596NoAcceleration(egl_platform::OPENGL_OR_GLES(), BigWorkload(), ExtensionName::multiview),597NoAcceleration(egl_platform::D3D11(), BigWorkload(), ExtensionName::multiview),598SelectViewInGeometryShader(BigWorkload(), ExtensionName::multiview),599SelectViewInVertexShader(egl_platform::OPENGL_OR_GLES(),600BigWorkload(),601ExtensionName::multiview),602SelectViewInVertexShader(egl_platform::D3D11(), BigWorkload(), ExtensionName::multiview),603NoAcceleration(egl_platform::OPENGL_OR_GLES(), BigWorkload(), ExtensionName::multiview2),604NoAcceleration(egl_platform::D3D11(), BigWorkload(), ExtensionName::multiview2),605SelectViewInGeometryShader(BigWorkload(), ExtensionName::multiview2),606SelectViewInVertexShader(egl_platform::OPENGL_OR_GLES(),607BigWorkload(),608ExtensionName::multiview2),609SelectViewInVertexShader(egl_platform::D3D11(), BigWorkload(), ExtensionName::multiview2));610611} // anonymous namespace612613614