Path: blob/main_old/src/tests/perf_tests/TextureSampling.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// TextureSamplingBenchmark:6// Performance test for texture sampling. The test generates a texture containing random data7// and then blurs it in a fragment shader using nearest neighbor sampling. The test is8// specifically designed to test overhead of GLSL's builtin texture*() functions that may result9// from how ANGLE translates them on each backend.10//1112#include "ANGLEPerfTest.h"1314#include <iostream>15#include <random>16#include <sstream>1718#include "util/shader_utils.h"1920using namespace angle;2122namespace23{24constexpr unsigned int kIterationsPerStep = 4;2526struct TextureSamplingParams final : public RenderTestParams27{28TextureSamplingParams()29{30iterationsPerStep = kIterationsPerStep;3132// Common default params33majorVersion = 3;34minorVersion = 0;35windowWidth = 720;36windowHeight = 720;3738numSamplers = 2;39textureSize = 32;40kernelSize = 3;41}4243std::string story() const override;44unsigned int numSamplers;45unsigned int textureSize;46unsigned int kernelSize;47};4849std::ostream &operator<<(std::ostream &os, const TextureSamplingParams ¶ms)50{51os << params.backendAndStory().substr(1);52return os;53}5455std::string TextureSamplingParams::story() const56{57std::stringstream strstr;5859strstr << RenderTestParams::story() << "_" << numSamplers << "samplers";6061return strstr.str();62}6364class TextureSamplingBenchmark : public ANGLERenderTest,65public ::testing::WithParamInterface<TextureSamplingParams>66{67public:68TextureSamplingBenchmark();6970void initializeBenchmark() override;71void destroyBenchmark() override;72void drawBenchmark() override;7374protected:75void initShaders();76void initVertexBuffer();77void initTextures();7879GLuint mProgram;80GLuint mBuffer;81std::vector<GLuint> mTextures;82};8384TextureSamplingBenchmark::TextureSamplingBenchmark()85: ANGLERenderTest("TextureSampling", GetParam()), mProgram(0u), mBuffer(0u)86{}8788void TextureSamplingBenchmark::initializeBenchmark()89{90const auto ¶ms = GetParam();9192// Verify "numSamplers" is within MAX_TEXTURE_IMAGE_UNITS limit93GLint maxTextureImageUnits;94glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits);9596if (params.numSamplers > static_cast<unsigned int>(maxTextureImageUnits))97{98FAIL() << "Sampler count (" << params.numSamplers << ")"99<< " exceeds maximum texture count: " << maxTextureImageUnits << std::endl;100}101initShaders();102initVertexBuffer();103initTextures();104glClearColor(0.0f, 0.0f, 0.0f, 0.0f);105glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());106107ASSERT_GL_NO_ERROR();108}109110void TextureSamplingBenchmark::initShaders()111{112const auto ¶ms = GetParam();113114std::stringstream vstrstr;115vstrstr << "attribute vec2 aPosition;\n"116"varying vec2 vTextureCoordinates;\n"117"void main()\n"118"{\n"119" vTextureCoordinates = (aPosition + vec2(1.0)) * 0.5;\n"120" gl_Position = vec4(aPosition, 0, 1.0);\n"121"}";122123std::stringstream fstrstr;124fstrstr << "precision mediump float;\n"125"varying vec2 vTextureCoordinates;\n";126for (unsigned int count = 0; count < params.numSamplers; count++)127{128fstrstr << "uniform sampler2D uSampler" << count << ";\n";129}130fstrstr << "void main()\n"131"{\n"132" const float inverseTextureSize = 1.0 / "133<< params.textureSize134<< ".0;\n"135" vec4 colorOut = vec4(0.0, 0.0, 0.0, 1.0);\n";136for (unsigned int count = 0; count < params.numSamplers; count++)137{138fstrstr << " for (int x = 0; x < " << params.kernelSize139<< "; ++x)\n"140" {\n"141" for (int y = 0; y < "142<< params.kernelSize143<< "; ++y)\n"144" {\n"145" colorOut += texture2D(uSampler"146<< count147<< ", vTextureCoordinates + vec2(x, y) * inverseTextureSize) * 0.1;\n"148" }\n"149" }\n";150}151fstrstr << " gl_FragColor = colorOut;\n"152"}\n";153154mProgram = CompileProgram(vstrstr.str().c_str(), fstrstr.str().c_str());155ASSERT_NE(0u, mProgram);156157// Use the program object158glUseProgram(mProgram);159}160161void TextureSamplingBenchmark::initVertexBuffer()162{163std::vector<float> vertexPositions(12);164{165// Bottom left triangle166vertexPositions[0] = -1.0f;167vertexPositions[1] = -1.0f;168vertexPositions[2] = 1.0f;169vertexPositions[3] = -1.0f;170vertexPositions[4] = -1.0f;171vertexPositions[5] = 1.0f;172173// Top right triangle174vertexPositions[6] = -1.0f;175vertexPositions[7] = 1.0f;176vertexPositions[8] = 1.0f;177vertexPositions[9] = -1.0f;178vertexPositions[10] = 1.0f;179vertexPositions[11] = 1.0f;180}181182glGenBuffers(1, &mBuffer);183glBindBuffer(GL_ARRAY_BUFFER, mBuffer);184glBufferData(GL_ARRAY_BUFFER, vertexPositions.size() * sizeof(float), &vertexPositions[0],185GL_STATIC_DRAW);186187GLint positionLocation = glGetAttribLocation(mProgram, "aPosition");188ASSERT_NE(-1, positionLocation);189190glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, nullptr);191glEnableVertexAttribArray(positionLocation);192}193194void TextureSamplingBenchmark::initTextures()195{196const auto ¶ms = GetParam();197198unsigned int dataSize = params.textureSize * params.textureSize;199std::vector<unsigned int> randomTextureData;200randomTextureData.resize(dataSize);201202unsigned int pseudoRandom = 1u;203for (unsigned int i = 0; i < dataSize; ++i)204{205pseudoRandom = pseudoRandom * 1664525u + 1013904223u;206randomTextureData[i] = pseudoRandom;207}208209mTextures.resize(params.numSamplers);210glGenTextures(params.numSamplers, mTextures.data());211for (unsigned int i = 0; i < params.numSamplers; ++i)212{213glActiveTexture(GL_TEXTURE0 + i);214glBindTexture(GL_TEXTURE_2D, mTextures[i]);215glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);216glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);217glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);218glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);219glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, params.textureSize, params.textureSize, 0, GL_RGBA,220GL_UNSIGNED_BYTE, randomTextureData.data());221}222223for (unsigned int count = 0; count < params.numSamplers; count++)224{225std::stringstream samplerstrstr;226samplerstrstr << "uSampler" << count;227GLint samplerLocation = glGetUniformLocation(mProgram, samplerstrstr.str().c_str());228ASSERT_NE(-1, samplerLocation);229230glUniform1i(samplerLocation, count);231}232}233234void TextureSamplingBenchmark::destroyBenchmark()235{236const auto ¶ms = GetParam();237238glDeleteProgram(mProgram);239glDeleteBuffers(1, &mBuffer);240if (!mTextures.empty())241{242glDeleteTextures(params.numSamplers, mTextures.data());243}244}245246void TextureSamplingBenchmark::drawBenchmark()247{248glClear(GL_COLOR_BUFFER_BIT);249250const auto ¶ms = GetParam();251252for (unsigned int it = 0; it < params.iterationsPerStep; ++it)253{254glDrawArrays(GL_TRIANGLES, 0, 6);255}256257ASSERT_GL_NO_ERROR();258}259260// Identical to TextureSamplingBenchmark, but enables and then disables261// EXT_texture_format_sRGB_override during initialization. This should force the internal texture262// representation to use VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, which is expected to carry a263// performance penalty. This penalty can be quantified by comparing the results of this test with264// the results from TextureSamplingBenchmark265class TextureSamplingMutableFormatBenchmark : public TextureSamplingBenchmark266{267public:268void initializeBenchmark() override;269270protected:271void initTextures();272};273274void TextureSamplingMutableFormatBenchmark::initializeBenchmark()275{276if (IsGLExtensionEnabled("GL_EXT_texture_format_sRGB_override"))277{278TextureSamplingBenchmark::initializeBenchmark();279initTextures();280}281}282283void TextureSamplingMutableFormatBenchmark::initTextures()284{285TextureSamplingBenchmark::initTextures();286287for (unsigned int i = 0; i < mTextures.size(); ++i)288{289glActiveTexture(GL_TEXTURE0 + i);290glBindTexture(GL_TEXTURE_2D, mTextures[i]);291glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_FORMAT_SRGB_OVERRIDE_EXT, GL_SRGB);292}293294// Force a state update295drawBenchmark();296297for (unsigned int i = 0; i < mTextures.size(); ++i)298{299glActiveTexture(GL_TEXTURE0 + i);300glBindTexture(GL_TEXTURE_2D, mTextures[i]);301glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_FORMAT_SRGB_OVERRIDE_EXT, GL_NONE);302}303}304305TextureSamplingParams D3D11Params()306{307TextureSamplingParams params;308params.eglParameters = egl_platform::D3D11();309return params;310}311312TextureSamplingParams OpenGLOrGLESParams()313{314TextureSamplingParams params;315params.eglParameters = egl_platform::OPENGL_OR_GLES();316return params;317}318319TextureSamplingParams VulkanParams()320{321TextureSamplingParams params;322params.eglParameters = egl_platform::VULKAN();323return params;324}325326} // anonymous namespace327328TEST_P(TextureSamplingBenchmark, Run)329{330ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_format_sRGB_override"));331run();332}333334TEST_P(TextureSamplingMutableFormatBenchmark, Run)335{336ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_format_sRGB_override"));337run();338}339340ANGLE_INSTANTIATE_TEST(TextureSamplingBenchmark,341D3D11Params(),342OpenGLOrGLESParams(),343VulkanParams());344345GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureSamplingMutableFormatBenchmark);346ANGLE_INSTANTIATE_TEST(TextureSamplingMutableFormatBenchmark, VulkanParams());347348349