Path: blob/main_old/src/tests/perf_tests/glmark2Benchmark.cpp
1693 views
//1// Copyright 2019 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// glmark2Benchmark:6// Runs the glmark2 benchmark.7//89#include <gtest/gtest.h>1011#include <stdio.h>12#include <sstream>1314#include "../perf_tests/third_party/perf/perf_result_reporter.h"15#include "ANGLEPerfTestArgs.h"16#include "common/platform.h"17#include "common/string_utils.h"18#include "common/system_utils.h"19#include "test_utils/angle_test_configs.h"20#include "test_utils/angle_test_instantiate.h"21#include "util/test_utils.h"2223using namespace angle;2425namespace26{2728struct BenchmarkInfo29{30const char *glmark2Config;31const char *name;32};3334// Each glmark2 scene is individually benchmarked. If glmark2 is run without a specific benchmark,35// it can produce an aggregate score, which is not interesting at the moment. Adding an empty36// string ("") to this list will enable a test where glmark2 is run with the default scenes and the37// score for each test as well as the overall score is output.38constexpr BenchmarkInfo kBenchmarks[] = {39{"build:use-vbo=false", "build"},40{"build:use-vbo=true", "build_vbo"},41{"texture:texture-filter=nearest", "texture_nearest"},42{"texture:texture-filter=linear", "texture_linear"},43{"texture:texture-filter=mipmap", "texture_mipmap"},44{"shading:shading=gouraud", "shading_gouraud"},45{"shading:shading=blinn-phong-inf", "shading_blinn_phong"},46{"shading:shading=phong", "shading_phong"},47{"shading:shading=cel", "shading_cel"},48{"bump:bump-render=high-poly", "bump_high_poly"},49{"bump:bump-render=normals", "bump_normals"},50{"bump:bump-render=height", "bump_height"},51{"effect2d:kernel=0,1,0;1,-4,1;0,1,0;", "effect2d_edge"},52{"effect2d:kernel=1,1,1,1,1;1,1,1,1,1;1,1,1,1,1;", "effect2d_blur"},53{"pulsar:light=false:quads=5:texture=false", "pulsar"},54{"desktop:blur-radius=5:effect=blur:passes=1:separable=true:windows=4", "desktop_blur"},55{"desktop:effect=shadow:windows=4", "desktop_shadow"},56{"buffer:columns=200:interleave=false:update-dispersion=0.9:update-fraction=0.5:update-method="57"map",58"buffer_map"},59{"buffer:columns=200:interleave=false:update-dispersion=0.9:update-fraction=0.5:update-method="60"subdata",61"buffer_subdata"},62{"buffer:columns=200:interleave=true:update-dispersion=0.9:update-fraction=0.5:update-method="63"map",64"buffer_map_interleave"},65{"ideas:speed=duration", "ideas"},66{"jellyfish", "jellyfish"},67{"terrain", "terrain"},68{"shadow", "shadow"},69{"refract", "refract"},70{"conditionals:fragment-steps=0:vertex-steps=0", "conditionals"},71{"conditionals:fragment-steps=5:vertex-steps=0", "conditionals_fragment"},72{"conditionals:fragment-steps=0:vertex-steps=5", "conditionals_vertex"},73{"function:fragment-complexity=low:fragment-steps=5", "function"},74{"function:fragment-complexity=medium:fragment-steps=5", "function_complex"},75{"loop:fragment-loop=false:fragment-steps=5:vertex-steps=5", "loop_no_fsloop"},76{"loop:fragment-steps=5:fragment-uniform=false:vertex-steps=5", "loop_no_uniform"},77{"loop:fragment-steps=5:fragment-uniform=true:vertex-steps=5", "loop"},78};7980struct GLMark2TestParams : public PlatformParameters81{82BenchmarkInfo info;83};8485std::ostream &operator<<(std::ostream &os, const GLMark2TestParams ¶ms)86{87os << static_cast<const PlatformParameters &>(params) << "_" << params.info.name;88return os;89}9091class GLMark2Benchmark : public testing::TestWithParam<GLMark2TestParams>92{93public:94GLMark2Benchmark()95{96switch (GetParam().getRenderer())97{98case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:99mBackend = "d3d11";100break;101case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:102mBackend = "gl";103break;104case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:105mBackend = "vulkan";106break;107default:108break;109}110std::string story = GetParam().info.name;111mReporter = std::make_unique<perf_test::PerfResultReporter>("glmark2_" + mBackend, story);112mReporter->RegisterImportantMetric(".fps", "fps");113mReporter->RegisterImportantMetric(".score", "score");114}115116void run()117{118// Only supported on Linux and Windows at the moment.119if (!IsLinux() && !IsWindows())120{121return;122}123124const BenchmarkInfo benchmarkInfo = GetParam().info;125const char *benchmark = benchmarkInfo.glmark2Config;126const char *benchmarkName = benchmarkInfo.name;127bool completeRun = benchmark == nullptr || benchmark[0] == '\0';128129Optional<std::string> cwd = GetCWD();130131// Set the current working directory to the executable's, as the data path of glmark2 is132// set relative to that path.133std::string executableDir = GetExecutableDirectory();134SetCWD(executableDir.c_str());135SetEnvironmentVar("ANGLE_DEFAULT_PLATFORM", mBackend.c_str());136137std::vector<const char *> args = {138"glmark2_angle",139};140if (OneFrame())141{142args.push_back("--validate");143}144if (!completeRun)145{146args.push_back("--benchmark");147args.push_back(benchmark);148fprintf(stderr, "Running benchmark: %s\n", benchmark);149}150args.push_back(nullptr);151152ProcessHandle process(args, ProcessOutputCapture::StdoutOnly);153ASSERT_TRUE(process && process->started());154ASSERT_TRUE(process->finish());155156// Restore the current working directory for the next tests.157if (cwd.valid())158{159SetCWD(cwd.value().c_str());160}161162ASSERT_EQ(EXIT_SUCCESS, process->getExitCode());163164if (!OneFrame())165{166std::string output = process->getStdout();167parseOutput(output, benchmarkName, completeRun);168}169}170171private:172void parseOutput(const std::string &output, const char *benchmarkName, bool completeRun)173{174// Output is in the following format:175//176// =======================================================177// glmark2 2017.07178// =======================================================179// OpenGL Information180// GL_VENDOR: ...181// GL_RENDERER: ...182// GL_VERSION: ...183// =======================================================184// [test] config: FPS: uint FrameTime: float ms185// [test] config: Not Supported186// ...187// =======================================================188// glmark2 Score: uint189// =======================================================190//191// This function skips the header, prints one line for each test/config line where there's192// an FPS value, and finally prints the overall score.193std::istringstream glmark2Output(output);194std::string line;195196// Forward any INFO: lines that may have been generated.197while (std::getline(glmark2Output, line) && BeginsWith(line, "INFO:"))198{199fprintf(stderr, "%s\n", line.c_str());200}201202// Expect ==== at the top of the header203ASSERT_EQ('=', line[0]);204205// Skip one line206std::getline(glmark2Output, line);207208// Expect ==== in the middle of the header209std::getline(glmark2Output, line);210ASSERT_EQ('=', line[0]);211212// Skip four lines213std::getline(glmark2Output, line);214std::getline(glmark2Output, line);215std::getline(glmark2Output, line);216std::getline(glmark2Output, line);217218// The fourth line is the GL_VERSION. Expect it to include ANGLE, otherwise we are not219// running against ANGLE.220ASSERT_NE(line.find("ANGLE"), std::string::npos);221222// Expect ==== at the bottom of the header223std::getline(glmark2Output, line);224ASSERT_EQ('=', line[0]);225226// Read configs until the top of the footer is reached227while (std::getline(glmark2Output, line) && line[0] != '=')228{229// Parse the line230std::istringstream lin(line);231232std::string testName, testConfig;233lin >> testName >> testConfig;234EXPECT_TRUE(lin);235236std::string fpsTag, frametimeTag;237size_t fps;238float frametime;239240lin >> fpsTag >> fps >> frametimeTag >> frametime;241242// If the line is not in `FPS: uint FrameTime: Float ms` format, the test is not243// supported. It will be skipped.244if (!lin)245{246continue;247}248249EXPECT_EQ("FPS:", fpsTag);250EXPECT_EQ("FrameTime:", frametimeTag);251252if (!completeRun)253{254mReporter->AddResult(".fps", fps);255}256}257258// Get the score line: `glmark2 Score: uint`259std::string glmark2Tag, scoreTag;260size_t score;261glmark2Output >> glmark2Tag >> scoreTag >> score;262EXPECT_TRUE(glmark2Output);263EXPECT_EQ("glmark2", glmark2Tag);264EXPECT_EQ("Score:", scoreTag);265266if (completeRun)267{268mReporter->AddResult(".score", score);269}270}271272std::string mBackend = "invalid";273std::unique_ptr<perf_test::PerfResultReporter> mReporter;274};275276TEST_P(GLMark2Benchmark, Run)277{278run();279}280281GLMark2TestParams CombineEGLPlatform(const GLMark2TestParams &in, EGLPlatformParameters eglParams)282{283GLMark2TestParams out = in;284out.eglParameters = eglParams;285return out;286}287288GLMark2TestParams CombineInfo(const GLMark2TestParams &in, BenchmarkInfo info)289{290GLMark2TestParams out = in;291out.info = info;292return out;293}294295using namespace egl_platform;296297std::vector<GLMark2TestParams> gTestsWithInfo =298CombineWithValues({GLMark2TestParams()}, kBenchmarks, CombineInfo);299std::vector<EGLPlatformParameters> gEGLPlatforms = {D3D11(), OPENGLES(), VULKAN()};300std::vector<GLMark2TestParams> gTestsWithPlatform =301CombineWithValues(gTestsWithInfo, gEGLPlatforms, CombineEGLPlatform);302303ANGLE_INSTANTIATE_TEST_ARRAY(GLMark2Benchmark, gTestsWithPlatform);304305} // namespace306307308