Path: blob/main_old/src/tests/perf_tests/UniformsPerf.cpp
1693 views
//1// Copyright 2016 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// UniformsBenchmark:6// Performance test for setting uniform data.7//89#include "ANGLEPerfTest.h"1011#include <array>12#include <iostream>13#include <random>14#include <sstream>1516#include "common/debug.h"17#include "util/Matrix.h"18#include "util/shader_utils.h"1920using namespace angle;2122namespace23{24constexpr unsigned int kIterationsPerStep = 4;2526// Controls when we call glUniform, if the data is the same as last frame.27enum DataMode28{29UPDATE,30REPEAT,31};3233// TODO(jmadill): Use an ANGLE enum for this?34enum DataType35{36VEC4,37MAT3x3,38MAT3x4,39MAT4x4,40};4142// Determines if we state change the program between draws.43// This covers a performance problem in ANGLE where calling UseProgram reuploads uniform data.44enum ProgramMode45{46SINGLE,47MULTIPLE,48};4950enum MatrixLayout51{52TRANSPOSE,53NO_TRANSPOSE,54};5556struct UniformsParams final : public RenderTestParams57{58UniformsParams()59{60iterationsPerStep = kIterationsPerStep;6162// Common default params63majorVersion = 3;64minorVersion = 0;65windowWidth = 720;66windowHeight = 720;67}6869std::string story() const override;70size_t numVertexUniforms = 200;71size_t numFragmentUniforms = 200;7273DataType dataType = DataType::VEC4;74DataMode dataMode = DataMode::REPEAT;75MatrixLayout matrixLayout = MatrixLayout::NO_TRANSPOSE;76ProgramMode programMode = ProgramMode::SINGLE;77};7879std::ostream &operator<<(std::ostream &os, const UniformsParams ¶ms)80{81os << params.backendAndStory().substr(1);82return os;83}8485std::string UniformsParams::story() const86{87std::stringstream strstr;8889strstr << RenderTestParams::story();9091if (dataType == DataType::VEC4)92{93strstr << "_" << (numVertexUniforms + numFragmentUniforms) << "_vec4";94}95else if (dataType == DataType::MAT3x3)96{97strstr << "_" << (numVertexUniforms + numFragmentUniforms) << "_mat3x3";98}99else if (dataType == DataType::MAT3x4)100{101strstr << "_" << (numVertexUniforms + numFragmentUniforms) << "_mat3x4";102}103else104{105strstr << "_" << (numVertexUniforms + numFragmentUniforms) << "_mat4x4";106}107108if (matrixLayout == MatrixLayout::TRANSPOSE)109{110strstr << "_transpose";111}112113if (programMode == ProgramMode::MULTIPLE)114{115strstr << "_multiprogram";116}117118if (dataMode == DataMode::REPEAT)119{120strstr << "_repeating";121}122123return strstr.str();124}125126class UniformsBenchmark : public ANGLERenderTest,127public ::testing::WithParamInterface<UniformsParams>128{129public:130UniformsBenchmark();131132void initializeBenchmark() override;133void destroyBenchmark() override;134void drawBenchmark() override;135136private:137void initShaders();138139template <bool MultiProgram, typename SetUniformFunc>140void drawLoop(const SetUniformFunc &setUniformsFunc);141142std::array<GLuint, 2> mPrograms;143std::vector<GLuint> mUniformLocations;144145using MatrixData = std::array<std::vector<Matrix4>, 2>;146MatrixData mMatrixData;147};148149std::vector<Matrix4> GenMatrixData(size_t count, int parity)150{151std::vector<Matrix4> data;152153// Very simple matrix data allocation scheme.154for (size_t index = 0; index < count; ++index)155{156Matrix4 mat;157for (int row = 0; row < 4; ++row)158{159for (int col = 0; col < 4; ++col)160{161mat.data[row * 4 + col] = (row * col + parity) % 2 == 0 ? 1.0f : -1.0f;162}163}164165data.push_back(mat);166}167168return data;169}170171UniformsBenchmark::UniformsBenchmark() : ANGLERenderTest("Uniforms", GetParam()), mPrograms({})172{173// Fails on Windows7 NVIDIA Vulkan, presumably due to old drivers. http://crbug.com/1096510174if (IsWindows7() && IsNVIDIA() &&175GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE)176{177mSkipTest = true;178}179}180181void UniformsBenchmark::initializeBenchmark()182{183const auto ¶ms = GetParam();184185// Verify the uniform counts are within the limits186GLint maxVertexUniformVectors, maxFragmentUniformVectors;187glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxVertexUniformVectors);188glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxFragmentUniformVectors);189190GLint vectorCountPerUniform;191bool isMatrix;192switch (params.dataType)193{194case DataType::MAT3x3:195vectorCountPerUniform = 3;196isMatrix = true;197break;198case DataType::MAT3x4:199// depends on transpose, conservatively set to 4200vectorCountPerUniform = 4;201isMatrix = true;202break;203case DataType::MAT4x4:204vectorCountPerUniform = 4;205isMatrix = true;206break;207default:208vectorCountPerUniform = 1;209isMatrix = false;210break;211}212213GLint numVertexUniformVectors =214static_cast<GLint>(params.numVertexUniforms) * vectorCountPerUniform;215GLint numFragmentUniformVectors =216static_cast<GLint>(params.numFragmentUniforms) * vectorCountPerUniform;217218if (numVertexUniformVectors > maxVertexUniformVectors)219{220FAIL() << "Vertex uniform vector count (" << numVertexUniformVectors << ")"221<< " exceeds maximum vertex uniform vector count: " << maxVertexUniformVectors222<< std::endl;223}224if (numFragmentUniformVectors > maxFragmentUniformVectors)225{226FAIL() << "Fragment uniform vector count (" << numFragmentUniformVectors << ")"227<< " exceeds maximum fragment uniform vector count: " << maxFragmentUniformVectors228<< std::endl;229}230231initShaders();232glClearColor(0.0f, 0.0f, 0.0f, 0.0f);233glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());234235if (isMatrix)236{237size_t count = params.numVertexUniforms + params.numFragmentUniforms;238239mMatrixData[0] = GenMatrixData(count, 0);240if (params.dataMode == DataMode::REPEAT)241{242mMatrixData[1] = GenMatrixData(count, 0);243}244else245{246mMatrixData[1] = GenMatrixData(count, 1);247}248}249250GLint attribLocation = glGetAttribLocation(mPrograms[0], "pos");251ASSERT_NE(-1, attribLocation);252ASSERT_EQ(attribLocation, glGetAttribLocation(mPrograms[1], "pos"));253glVertexAttrib4f(attribLocation, 1.0f, 0.0f, 0.0f, 1.0f);254255ASSERT_GL_NO_ERROR();256}257258std::string GetUniformLocationName(size_t idx, bool vertexShader)259{260std::stringstream strstr;261strstr << (vertexShader ? "vs" : "fs") << "_u_" << idx;262return strstr.str();263}264265void UniformsBenchmark::initShaders()266{267const auto ¶ms = GetParam();268269const std::string kUniformVarPlaceHolder = "%s";270std::string typeString;271std::string uniformOperationTemplate;272switch (params.dataType)273{274case DataType::VEC4:275typeString = "vec4";276uniformOperationTemplate = kUniformVarPlaceHolder;277break;278case DataType::MAT3x3:279typeString = "mat3";280uniformOperationTemplate =281"mat4(" + kUniformVarPlaceHolder + ") * vec4(1.0, 1.0, 1.0, 1.0)";282break;283case DataType::MAT3x4:284typeString = "mat3x4";285uniformOperationTemplate =286"mat4(" + kUniformVarPlaceHolder + ") * vec4(1.0, 1.0, 1.0, 1.0)";287break;288case DataType::MAT4x4:289typeString = "mat4";290uniformOperationTemplate = kUniformVarPlaceHolder + "* vec4(1.0, 1.0, 1.0, 1.0)";291break;292default:293UNREACHABLE();294}295296std::stringstream vstrstr;297vstrstr << "#version 300 es\n";298vstrstr << "precision mediump float;\n";299vstrstr << "in vec4 pos;\n";300301for (size_t i = 0; i < params.numVertexUniforms; i++)302{303vstrstr << "uniform " << typeString << " " << GetUniformLocationName(i, true) << ";\n";304}305306vstrstr << "void main()\n"307"{\n"308" gl_Position = pos;\n";309for (size_t i = 0; i < params.numVertexUniforms; i++)310{311std::string uniformOperation = uniformOperationTemplate;312std::size_t pos = uniformOperation.find(kUniformVarPlaceHolder);313ASSERT(pos != std::string::npos);314uniformOperation.replace(pos, kUniformVarPlaceHolder.size(),315GetUniformLocationName(i, true));316vstrstr << " gl_Position += ";317vstrstr << uniformOperation;318vstrstr << ";\n";319}320vstrstr << "}";321322std::stringstream fstrstr;323fstrstr << "#version 300 es\n";324fstrstr << "precision mediump float;\n";325fstrstr << "out vec4 fragColor;\n";326327for (size_t i = 0; i < params.numFragmentUniforms; i++)328{329fstrstr << "uniform " << typeString << " " << GetUniformLocationName(i, false) << ";\n";330}331fstrstr << "void main()\n"332"{\n"333" fragColor = vec4(0, 0, 0, 0);\n";334for (size_t i = 0; i < params.numFragmentUniforms; i++)335{336std::string uniformOperation = uniformOperationTemplate;337std::size_t pos = uniformOperation.find(kUniformVarPlaceHolder);338ASSERT(pos != std::string::npos);339uniformOperation.replace(pos, kUniformVarPlaceHolder.size(),340GetUniformLocationName(i, false));341fstrstr << " fragColor += ";342fstrstr << uniformOperation;343fstrstr << ";\n";344}345fstrstr << "}";346347mPrograms[0] = CompileProgram(vstrstr.str().c_str(), fstrstr.str().c_str());348ASSERT_NE(0u, mPrograms[0]);349mPrograms[1] = CompileProgram(vstrstr.str().c_str(), fstrstr.str().c_str());350ASSERT_NE(0u, mPrograms[1]);351352for (size_t i = 0; i < params.numVertexUniforms; ++i)353{354std::string name = GetUniformLocationName(i, true);355GLint location = glGetUniformLocation(mPrograms[0], name.c_str());356ASSERT_NE(-1, location);357ASSERT_EQ(location, glGetUniformLocation(mPrograms[1], name.c_str()));358mUniformLocations.push_back(location);359}360for (size_t i = 0; i < params.numFragmentUniforms; ++i)361{362std::string name = GetUniformLocationName(i, false);363GLint location = glGetUniformLocation(mPrograms[0], name.c_str());364ASSERT_NE(-1, location);365ASSERT_EQ(location, glGetUniformLocation(mPrograms[1], name.c_str()));366mUniformLocations.push_back(location);367}368369// Use the program object370glUseProgram(mPrograms[0]);371}372373void UniformsBenchmark::destroyBenchmark()374{375glDeleteProgram(mPrograms[0]);376glDeleteProgram(mPrograms[1]);377}378379// Hopefully the compiler is smart enough to inline the lambda setUniformsFunc.380template <bool MultiProgram, typename SetUniformFunc>381void UniformsBenchmark::drawLoop(const SetUniformFunc &setUniformsFunc)382{383const auto ¶ms = GetParam();384385size_t frameIndex = 0;386387for (size_t it = 0; it < params.iterationsPerStep; ++it, frameIndex = (frameIndex == 0 ? 1 : 0))388{389if (MultiProgram)390{391glUseProgram(mPrograms[frameIndex]);392}393if (params.dataMode == DataMode::UPDATE)394{395for (size_t uniform = 0; uniform < mUniformLocations.size(); ++uniform)396{397setUniformsFunc(mUniformLocations, mMatrixData, uniform, frameIndex);398}399}400glDrawArrays(GL_TRIANGLES, 0, 3);401}402}403404void UniformsBenchmark::drawBenchmark()405{406const auto ¶ms = GetParam();407408GLboolean transpose = static_cast<GLboolean>(params.matrixLayout == MatrixLayout::TRANSPOSE);409410switch (params.dataType)411{412case DataType::MAT4x4:413{414auto setFunc = [=](const std::vector<GLuint> &locations, const MatrixData &matrixData,415size_t uniform, size_t frameIndex) {416glUniformMatrix4fv(locations[uniform], 1, transpose,417matrixData[frameIndex][uniform].data);418};419420drawLoop<false>(setFunc);421break;422}423case DataType::MAT3x4:424{425auto setFunc = [=](const std::vector<GLuint> &locations, const MatrixData &matrixData,426size_t uniform, size_t frameIndex) {427glUniformMatrix3x4fv(locations[uniform], 1, transpose,428matrixData[frameIndex][uniform].data);429};430431drawLoop<false>(setFunc);432break;433}434case DataType::MAT3x3:435{436auto setFunc = [=](const std::vector<GLuint> &locations, const MatrixData &matrixData,437size_t uniform, size_t frameIndex) {438glUniformMatrix3fv(locations[uniform], 1, transpose,439matrixData[frameIndex][uniform].data);440};441442drawLoop<false>(setFunc);443break;444}445case DataType::VEC4:446{447auto setFunc = [](const std::vector<GLuint> &locations, const MatrixData &matrixData,448size_t uniform, size_t frameIndex) {449float value = static_cast<float>(uniform);450glUniform4f(locations[uniform], value, value, value, value);451};452453if (params.programMode == ProgramMode::MULTIPLE)454{455drawLoop<true>(setFunc);456}457else458{459drawLoop<false>(setFunc);460}461break;462}463default:464UNREACHABLE();465}466467ASSERT_GL_NO_ERROR();468}469470using namespace egl_platform;471472UniformsParams VectorUniforms(const EGLPlatformParameters &egl,473DataMode dataMode,474ProgramMode programMode = ProgramMode::SINGLE)475{476UniformsParams params;477params.eglParameters = egl;478params.dataMode = dataMode;479params.programMode = programMode;480return params;481}482483UniformsParams MatrixUniforms(const EGLPlatformParameters &egl,484DataMode dataMode,485DataType dataType,486MatrixLayout matrixLayout)487{488UniformsParams params;489params.eglParameters = egl;490params.dataType = dataType;491params.dataMode = dataMode;492params.matrixLayout = matrixLayout;493494// Reduce the number of uniforms to fit within smaller upper limits on some configs.495params.numVertexUniforms = 55;496params.numFragmentUniforms = 55;497498return params;499}500501} // anonymous namespace502503TEST_P(UniformsBenchmark, Run)504{505run();506}507508ANGLE_INSTANTIATE_TEST(509UniformsBenchmark,510VectorUniforms(D3D11(), DataMode::REPEAT),511VectorUniforms(D3D11(), DataMode::UPDATE),512VectorUniforms(D3D11_NULL(), DataMode::UPDATE),513VectorUniforms(OPENGL_OR_GLES(), DataMode::UPDATE),514VectorUniforms(OPENGL_OR_GLES(), DataMode::REPEAT),515VectorUniforms(OPENGL_OR_GLES_NULL(), DataMode::UPDATE),516MatrixUniforms(D3D11(), DataMode::UPDATE, DataType::MAT4x4, MatrixLayout::NO_TRANSPOSE),517MatrixUniforms(OPENGL_OR_GLES(),518DataMode::UPDATE,519DataType::MAT4x4,520MatrixLayout::NO_TRANSPOSE),521MatrixUniforms(VULKAN_NULL(), DataMode::UPDATE, DataType::MAT4x4, MatrixLayout::NO_TRANSPOSE),522MatrixUniforms(VULKAN_NULL(), DataMode::UPDATE, DataType::MAT4x4, MatrixLayout::TRANSPOSE),523MatrixUniforms(VULKAN_NULL(), DataMode::REPEAT, DataType::MAT4x4, MatrixLayout::NO_TRANSPOSE),524MatrixUniforms(VULKAN_NULL(), DataMode::UPDATE, DataType::MAT3x4, MatrixLayout::NO_TRANSPOSE),525MatrixUniforms(VULKAN_NULL(), DataMode::UPDATE, DataType::MAT3x3, MatrixLayout::TRANSPOSE),526MatrixUniforms(VULKAN_NULL(), DataMode::REPEAT, DataType::MAT3x3, MatrixLayout::TRANSPOSE),527MatrixUniforms(VULKAN(), DataMode::UPDATE, DataType::MAT4x4, MatrixLayout::NO_TRANSPOSE),528MatrixUniforms(VULKAN(), DataMode::REPEAT, DataType::MAT4x4, MatrixLayout::NO_TRANSPOSE),529MatrixUniforms(VULKAN(), DataMode::UPDATE, DataType::MAT3x3, MatrixLayout::NO_TRANSPOSE),530MatrixUniforms(VULKAN(), DataMode::REPEAT, DataType::MAT3x3, MatrixLayout::NO_TRANSPOSE),531VectorUniforms(D3D11_NULL(), DataMode::REPEAT, ProgramMode::MULTIPLE));532533534