Path: blob/main_old/src/tests/perf_tests/InstancingPerf.cpp
1693 views
//1// Copyright 2015 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// InstancingPerf:6// Performance tests for ANGLE instanced draw calls.7//89#include "ANGLEPerfTest.h"1011#include <cmath>12#include <sstream>1314#include "util/Matrix.h"15#include "util/random_utils.h"16#include "util/shader_utils.h"1718using namespace angle;19using namespace egl_platform;2021namespace22{2324float AnimationSignal(float t)25{26float l = t / 2.0f;27float f = l - std::floor(l);28return (f > 0.5f ? 1.0f - f : f) * 4.0f - 1.0f;29}3031template <typename T>32size_t VectorSizeBytes(const std::vector<T> &vec)33{34return sizeof(T) * vec.size();35}3637Vector3 RandomVector3(RNG *rng)38{39return Vector3(rng->randomNegativeOneToOne(), rng->randomNegativeOneToOne(),40rng->randomNegativeOneToOne());41}4243struct InstancingPerfParams final : public RenderTestParams44{45// Common default options46InstancingPerfParams()47{48majorVersion = 2;49minorVersion = 0;50windowWidth = 256;51windowHeight = 256;52iterationsPerStep = 1;53runTimeSeconds = 10.0;54animationEnabled = false;55instancingEnabled = true;56}5758std::string story() const override59{60std::stringstream strstr;6162strstr << RenderTestParams::story();6364if (!instancingEnabled)65{66strstr << "_billboards";67}6869return strstr.str();70}7172double runTimeSeconds;73bool animationEnabled;74bool instancingEnabled;75};7677std::ostream &operator<<(std::ostream &os, const InstancingPerfParams ¶ms)78{79os << params.backendAndStory().substr(1);80return os;81}8283class InstancingPerfBenchmark : public ANGLERenderTest,84public ::testing::WithParamInterface<InstancingPerfParams>85{86public:87InstancingPerfBenchmark();8889void initializeBenchmark() override;90void destroyBenchmark() override;91void drawBenchmark() override;9293private:94GLuint mProgram;95std::vector<GLuint> mBuffers;96GLuint mNumPoints;97std::vector<Vector3> mTranslateData;98std::vector<float> mSizeData;99std::vector<Vector3> mColorData;100angle::RNG mRNG;101};102103InstancingPerfBenchmark::InstancingPerfBenchmark()104: ANGLERenderTest("InstancingPerf", GetParam()), mProgram(0), mNumPoints(75000)105{}106107void InstancingPerfBenchmark::initializeBenchmark()108{109const auto ¶ms = GetParam();110111const char kVS[] =112"attribute vec2 aPosition;\n"113"attribute vec3 aTranslate;\n"114"attribute float aScale;\n"115"attribute vec3 aColor;\n"116"uniform mat4 uWorldMatrix;\n"117"uniform mat4 uProjectionMatrix;\n"118"varying vec3 vColor;\n"119"void main()\n"120"{\n"121" vec4 position = uWorldMatrix * vec4(aTranslate, 1.0);\n"122" position.xy += aPosition * aScale;\n"123" gl_Position = uProjectionMatrix * position;\n"124" vColor = aColor;\n"125"}\n";126127constexpr char kFS[] =128"precision mediump float;\n"129"varying vec3 vColor;\n"130"void main()\n"131"{\n"132" gl_FragColor = vec4(vColor, 1.0);\n"133"}\n";134135mProgram = CompileProgram(kVS, kFS);136ASSERT_NE(0u, mProgram);137138glUseProgram(mProgram);139140glClearColor(0.0f, 0.0f, 0.0f, 0.0f);141142GLuint baseIndexData[6] = {0, 1, 2, 1, 3, 2};143Vector2 basePositionData[4] = {Vector2(-1.0f, 1.0f), Vector2(1.0f, 1.0f), Vector2(-1.0f, -1.0f),144Vector2(1.0f, -1.0f)};145146std::vector<GLuint> indexData;147std::vector<Vector2> positionData;148149if (!params.instancingEnabled)150{151GLuint pointVertexStride = 4;152for (GLuint pointIndex = 0; pointIndex < mNumPoints; ++pointIndex)153{154for (GLuint indexIndex = 0; indexIndex < 6; ++indexIndex)155{156indexData.push_back(baseIndexData[indexIndex] + pointIndex * pointVertexStride);157}158159Vector3 randVec = RandomVector3(&mRNG);160for (GLuint vertexIndex = 0; vertexIndex < 4; ++vertexIndex)161{162positionData.push_back(basePositionData[vertexIndex]);163mTranslateData.push_back(randVec);164}165}166167mSizeData.resize(mNumPoints * 4, 0.012f);168mColorData.resize(mNumPoints * 4, Vector3(1.0f, 0.0f, 0.0f));169}170else171{172for (GLuint index : baseIndexData)173{174indexData.push_back(index);175}176177for (const Vector2 &position : basePositionData)178{179positionData.push_back(position);180}181182for (GLuint pointIndex = 0; pointIndex < mNumPoints; ++pointIndex)183{184Vector3 randVec = RandomVector3(&mRNG);185mTranslateData.push_back(randVec);186}187188mSizeData.resize(mNumPoints, 0.012f);189mColorData.resize(mNumPoints, Vector3(1.0f, 0.0f, 0.0f));190}191192mBuffers.resize(5, 0);193glGenBuffers(static_cast<GLsizei>(mBuffers.size()), &mBuffers[0]);194195// Index Data196glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBuffers[0]);197glBufferData(GL_ELEMENT_ARRAY_BUFFER, VectorSizeBytes(indexData), &indexData[0],198GL_STATIC_DRAW);199200// Position Data201glBindBuffer(GL_ARRAY_BUFFER, mBuffers[1]);202glBufferData(GL_ARRAY_BUFFER, VectorSizeBytes(positionData), &positionData[0], GL_STATIC_DRAW);203GLint positionLocation = glGetAttribLocation(mProgram, "aPosition");204ASSERT_NE(-1, positionLocation);205glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 8, nullptr);206glEnableVertexAttribArray(positionLocation);207208// Translate Data209glBindBuffer(GL_ARRAY_BUFFER, mBuffers[2]);210glBufferData(GL_ARRAY_BUFFER, VectorSizeBytes(mTranslateData), &mTranslateData[0],211GL_STATIC_DRAW);212GLint translateLocation = glGetAttribLocation(mProgram, "aTranslate");213ASSERT_NE(-1, translateLocation);214glVertexAttribPointer(translateLocation, 3, GL_FLOAT, GL_FALSE, 12, nullptr);215glEnableVertexAttribArray(translateLocation);216glVertexAttribDivisorANGLE(translateLocation, 1);217218// Scale Data219glBindBuffer(GL_ARRAY_BUFFER, mBuffers[3]);220glBufferData(GL_ARRAY_BUFFER, VectorSizeBytes(mSizeData), nullptr, GL_DYNAMIC_DRAW);221GLint scaleLocation = glGetAttribLocation(mProgram, "aScale");222ASSERT_NE(-1, scaleLocation);223glVertexAttribPointer(scaleLocation, 1, GL_FLOAT, GL_FALSE, 4, nullptr);224glEnableVertexAttribArray(scaleLocation);225glVertexAttribDivisorANGLE(scaleLocation, 1);226227// Color Data228glBindBuffer(GL_ARRAY_BUFFER, mBuffers[4]);229glBufferData(GL_ARRAY_BUFFER, VectorSizeBytes(mColorData), nullptr, GL_DYNAMIC_DRAW);230GLint colorLocation = glGetAttribLocation(mProgram, "aColor");231ASSERT_NE(-1, colorLocation);232glVertexAttribPointer(colorLocation, 3, GL_FLOAT, GL_FALSE, 12, nullptr);233glEnableVertexAttribArray(colorLocation);234glVertexAttribDivisorANGLE(colorLocation, 1);235236// Set the viewport237glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());238239// Init matrices240GLint worldMatrixLocation = glGetUniformLocation(mProgram, "uWorldMatrix");241ASSERT_NE(-1, worldMatrixLocation);242Matrix4 worldMatrix = Matrix4::translate(Vector3(0, 0, -3.0f));243worldMatrix *= Matrix4::rotate(25.0f, Vector3(0.6f, 1.0f, 0.0f));244glUniformMatrix4fv(worldMatrixLocation, 1, GL_FALSE, &worldMatrix.data[0]);245246GLint projectionMatrixLocation = glGetUniformLocation(mProgram, "uProjectionMatrix");247ASSERT_NE(-1, projectionMatrixLocation);248float fov =249static_cast<float>(getWindow()->getWidth()) / static_cast<float>(getWindow()->getHeight());250Matrix4 projectionMatrix = Matrix4::perspective(60.0f, fov, 1.0f, 300.0f);251glUniformMatrix4fv(projectionMatrixLocation, 1, GL_FALSE, &projectionMatrix.data[0]);252253getWindow()->setVisible(true);254255ASSERT_GL_NO_ERROR();256}257258void InstancingPerfBenchmark::destroyBenchmark()259{260glDeleteProgram(mProgram);261262if (!mBuffers.empty())263{264glDeleteBuffers(static_cast<GLsizei>(mBuffers.size()), &mBuffers[0]);265mBuffers.clear();266}267}268269void InstancingPerfBenchmark::drawBenchmark()270{271glClear(GL_COLOR_BUFFER_BIT);272273const auto ¶ms = GetParam();274275// Animatino makes the test more interesting visually, but also eats up many CPU cycles.276if (params.animationEnabled)277{278float time = static_cast<float>(mTimer.getElapsedTime());279280for (size_t pointIndex = 0; pointIndex < mTranslateData.size(); ++pointIndex)281{282const Vector3 &translate = mTranslateData[pointIndex];283284float tx = translate.x() + time;285float ty = translate.y() + time;286float tz = translate.z() + time;287288float scale = AnimationSignal(tx) * 0.01f + 0.01f;289mSizeData[pointIndex] = scale;290291Vector3 color =292Vector3(AnimationSignal(tx), AnimationSignal(ty), AnimationSignal(tz)) * 0.5f +293Vector3(0.5f);294295mColorData[pointIndex] = color;296}297}298299// Update scales and colors.300glBindBuffer(GL_ARRAY_BUFFER, mBuffers[3]);301glBufferSubData(GL_ARRAY_BUFFER, 0, VectorSizeBytes(mSizeData), &mSizeData[0]);302303glBindBuffer(GL_ARRAY_BUFFER, mBuffers[4]);304glBufferSubData(GL_ARRAY_BUFFER, 0, VectorSizeBytes(mColorData), &mColorData[0]);305306// Render the instances/billboards.307if (params.instancingEnabled)308{309for (unsigned int it = 0; it < params.iterationsPerStep; it++)310{311glDrawElementsInstancedANGLE(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr, mNumPoints);312}313}314else315{316for (unsigned int it = 0; it < params.iterationsPerStep; it++)317{318glDrawElements(GL_TRIANGLES, 6 * mNumPoints, GL_UNSIGNED_INT, nullptr);319}320}321322ASSERT_GL_NO_ERROR();323}324325InstancingPerfParams InstancingPerfD3D11Params()326{327InstancingPerfParams params;328params.eglParameters = D3D11();329return params;330}331332InstancingPerfParams InstancingPerfOpenGLOrGLESParams()333{334InstancingPerfParams params;335params.eglParameters = OPENGL_OR_GLES();336return params;337}338339TEST_P(InstancingPerfBenchmark, Run)340{341run();342}343344ANGLE_INSTANTIATE_TEST(InstancingPerfBenchmark,345InstancingPerfD3D11Params(),346InstancingPerfOpenGLOrGLESParams());347348} // anonymous namespace349350351