Path: blob/main_old/src/tests/perf_tests/GenerateMipmapPerf.cpp
1693 views
//1// Copyright 2020 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// GenerateMipmapBenchmark:6// Performance test for generating texture mipmaps.7//89#include "ANGLEPerfTest.h"1011#include <iostream>12#include <random>13#include <sstream>1415#include "test_utils/gl_raii.h"16#include "util/shader_utils.h"1718using namespace angle;1920namespace21{22constexpr unsigned int kIterationsPerStep = 5;2324struct GenerateMipmapParams final : public RenderTestParams25{26GenerateMipmapParams()27{28iterationsPerStep = kIterationsPerStep;29trackGpuTime = true;3031textureWidth = 1920;32textureHeight = 1080;3334internalFormat = GL_RGBA;3536webgl = false;37}3839std::string story() const override;4041GLsizei textureWidth;42GLsizei textureHeight;4344GLenum internalFormat;4546bool webgl;47};4849std::ostream &operator<<(std::ostream &os, const GenerateMipmapParams ¶ms)50{51return os << params.backendAndStory().substr(1);52}5354std::string GenerateMipmapParams::story() const55{56std::stringstream strstr;5758strstr << RenderTestParams::story();5960if (webgl)61{62strstr << "_webgl";63}6465if (internalFormat == GL_RGB)66{67strstr << "_rgb";68}6970return strstr.str();71}7273template <typename T>74void FillWithRandomData(T *storage)75{76for (uint8_t &u : *storage)77{78u = rand() & 0xFF;79}80}8182class GenerateMipmapBenchmarkBase : public ANGLERenderTest,83public ::testing::WithParamInterface<GenerateMipmapParams>84{85public:86GenerateMipmapBenchmarkBase(const char *benchmarkName);8788void initializeBenchmark() override;89void destroyBenchmark() override;9091protected:92void initShaders();9394GLuint mProgram = 0;95GLuint mTexture = 0;9697std::vector<uint8_t> mTextureData;98};99100class GenerateMipmapBenchmark : public GenerateMipmapBenchmarkBase101{102public:103GenerateMipmapBenchmark() : GenerateMipmapBenchmarkBase("GenerateMipmap") {}104105void initializeBenchmark() override;106107void drawBenchmark() override;108};109110class GenerateMipmapWithRedefineBenchmark : public GenerateMipmapBenchmarkBase111{112public:113GenerateMipmapWithRedefineBenchmark()114: GenerateMipmapBenchmarkBase("GenerateMipmapWithRedefine")115{}116117void drawBenchmark() override;118};119120GenerateMipmapBenchmarkBase::GenerateMipmapBenchmarkBase(const char *benchmarkName)121: ANGLERenderTest(benchmarkName, GetParam())122{123setWebGLCompatibilityEnabled(GetParam().webgl);124setRobustResourceInit(GetParam().webgl);125126// Crashes on nvidia+d3d11. http://crbug.com/945415127if (GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)128{129mSkipTest = true;130}131132// Fails on Windows7 NVIDIA Vulkan, presumably due to old drivers. http://crbug.com/1096510133if (IsWindows7() && IsNVIDIA() &&134GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE)135{136mSkipTest = true;137}138}139140void GenerateMipmapBenchmarkBase::initializeBenchmark()141{142const auto ¶ms = GetParam();143144initShaders();145glClearColor(0.0f, 0.0f, 0.0f, 0.0f);146glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());147148if (mIsTimestampQueryAvailable && params.webgl)149{150glRequestExtensionANGLE("GL_EXT_disjoint_timer_query");151}152153glGenTextures(1, &mTexture);154glBindTexture(GL_TEXTURE_2D, mTexture);155156glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);157glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);158glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);159glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);160161mTextureData.resize(params.textureWidth * params.textureHeight * 4);162FillWithRandomData(&mTextureData);163164glTexImage2D(GL_TEXTURE_2D, 0, params.internalFormat, params.textureWidth, params.textureHeight,1650, params.internalFormat, GL_UNSIGNED_BYTE, mTextureData.data());166167// Perform a draw so the image data is flushed.168glDrawArrays(GL_TRIANGLES, 0, 3);169170glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);171172ASSERT_GL_NO_ERROR();173}174175void GenerateMipmapBenchmarkBase::initShaders()176{177constexpr char kVS[] = R"(void main()178{179gl_Position = vec4(0, 0, 0, 1);180})";181182constexpr char kFS[] = R"(precision mediump float;183void main()184{185gl_FragColor = vec4(0);186})";187188mProgram = CompileProgram(kVS, kFS);189ASSERT_NE(0u, mProgram);190191glUseProgram(mProgram);192193glDisable(GL_DEPTH_TEST);194195ASSERT_GL_NO_ERROR();196}197198void GenerateMipmapBenchmarkBase::destroyBenchmark()199{200glDeleteTextures(1, &mTexture);201glDeleteProgram(mProgram);202}203204void GenerateMipmapBenchmark::initializeBenchmark()205{206GenerateMipmapBenchmarkBase::initializeBenchmark();207208// Generate mipmaps once so the texture doesn't need to be redefined.209glGenerateMipmap(GL_TEXTURE_2D);210211// Perform a draw so the image data is flushed.212glDrawArrays(GL_TRIANGLES, 0, 3);213}214215void GenerateMipmapBenchmark::drawBenchmark()216{217const auto ¶ms = GetParam();218219startGpuTimer();220for (unsigned int iteration = 0; iteration < params.iterationsPerStep; ++iteration)221{222// Slightly modify the base texture so the mipmap is definitely regenerated.223std::array<uint8_t, 4> randomData;224FillWithRandomData(&randomData);225226glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, params.internalFormat, GL_UNSIGNED_BYTE,227randomData.data());228229// Generate mipmaps230glGenerateMipmap(GL_TEXTURE_2D);231232// Perform a draw just so the texture data is flushed. With the position attributes not233// set, a constant default value is used, resulting in a very cheap draw.234glDrawArrays(GL_TRIANGLES, 0, 3);235}236stopGpuTimer();237238ASSERT_GL_NO_ERROR();239}240241void GenerateMipmapWithRedefineBenchmark::drawBenchmark()242{243const auto ¶ms = GetParam();244245// Create a new texture every time, so image redefinition happens every time.246GLTexture texture;247glBindTexture(GL_TEXTURE_2D, texture);248249glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);250glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);251glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);252glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);253254glTexImage2D(GL_TEXTURE_2D, 0, params.internalFormat, params.textureWidth, params.textureHeight,2550, params.internalFormat, GL_UNSIGNED_BYTE, mTextureData.data());256257// Perform a draw so the image data is flushed.258glDrawArrays(GL_TRIANGLES, 0, 3);259260glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);261262startGpuTimer();263264// Do a single iteration, otherwise the cost of redefinition is amortized.265ASSERT_EQ(params.iterationsPerStep, 1u);266267// Generate mipmaps268glGenerateMipmap(GL_TEXTURE_2D);269270// Perform a draw just so the texture data is flushed. With the position attributes not271// set, a constant default value is used, resulting in a very cheap draw.272glDrawArrays(GL_TRIANGLES, 0, 3);273274stopGpuTimer();275276ASSERT_GL_NO_ERROR();277}278279GenerateMipmapParams D3D11Params(bool webglCompat, bool singleIteration)280{281GenerateMipmapParams params;282params.eglParameters = egl_platform::D3D11();283params.majorVersion = 3;284params.minorVersion = 0;285params.webgl = webglCompat;286if (singleIteration)287{288params.iterationsPerStep = 1;289}290return params;291}292293GenerateMipmapParams OpenGLOrGLESParams(bool webglCompat, bool singleIteration)294{295GenerateMipmapParams params;296params.eglParameters = egl_platform::OPENGL_OR_GLES();297params.majorVersion = 3;298params.minorVersion = 0;299params.webgl = webglCompat;300if (singleIteration)301{302params.iterationsPerStep = 1;303}304return params;305}306307GenerateMipmapParams VulkanParams(bool webglCompat, bool singleIteration, bool emulatedFormat)308{309GenerateMipmapParams params;310params.eglParameters = egl_platform::VULKAN();311params.majorVersion = 3;312params.minorVersion = 0;313params.webgl = webglCompat;314if (emulatedFormat)315{316params.internalFormat = GL_RGB;317}318if (singleIteration)319{320params.iterationsPerStep = 1;321}322return params;323}324325} // anonymous namespace326327TEST_P(GenerateMipmapBenchmark, Run)328{329run();330}331332TEST_P(GenerateMipmapWithRedefineBenchmark, Run)333{334run();335}336337using namespace params;338339ANGLE_INSTANTIATE_TEST(GenerateMipmapBenchmark,340D3D11Params(false, false),341D3D11Params(true, false),342OpenGLOrGLESParams(false, false),343OpenGLOrGLESParams(true, false),344VulkanParams(false, false, false),345VulkanParams(true, false, false),346VulkanParams(false, false, true),347VulkanParams(true, false, true));348349ANGLE_INSTANTIATE_TEST(GenerateMipmapWithRedefineBenchmark,350D3D11Params(false, true),351D3D11Params(true, true),352OpenGLOrGLESParams(false, true),353OpenGLOrGLESParams(true, true),354VulkanParams(false, true, false),355VulkanParams(true, true, false),356VulkanParams(false, true, true),357VulkanParams(true, true, true));358359360