diff options
Diffstat (limited to 'gfx/angle/src/tests/perf_tests/TextureSampling.cpp')
-rwxr-xr-x | gfx/angle/src/tests/perf_tests/TextureSampling.cpp | 288 |
1 files changed, 288 insertions, 0 deletions
diff --git a/gfx/angle/src/tests/perf_tests/TextureSampling.cpp b/gfx/angle/src/tests/perf_tests/TextureSampling.cpp new file mode 100755 index 000000000..bc00acddf --- /dev/null +++ b/gfx/angle/src/tests/perf_tests/TextureSampling.cpp @@ -0,0 +1,288 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// TextureSamplingBenchmark: +// Performance test for texture sampling. The test generates a texture containing random data +// and then blurs it in a fragment shader using nearest neighbor sampling. The test is +// specifically designed to test overhead of GLSL's builtin texture*() functions that may result +// from how ANGLE translates them on each backend. +// + +#include "ANGLEPerfTest.h" + +#include <iostream> +#include <random> +#include <sstream> + +#include "shader_utils.h" + +using namespace angle; + +namespace +{ + +struct TextureSamplingParams final : public RenderTestParams +{ + TextureSamplingParams() + { + // Common default params + majorVersion = 2; + minorVersion = 0; + windowWidth = 720; + windowHeight = 720; + iterations = 4; + + numSamplers = 2; + textureSize = 32; + kernelSize = 3; + } + + std::string suffix() const override; + unsigned int numSamplers; + unsigned int textureSize; + unsigned int kernelSize; + + // static parameters + unsigned int iterations; +}; + +std::ostream &operator<<(std::ostream &os, const TextureSamplingParams ¶ms) +{ + os << params.suffix().substr(1); + return os; +} + +std::string TextureSamplingParams::suffix() const +{ + std::stringstream strstr; + + strstr << RenderTestParams::suffix() << "_" << numSamplers << "samplers"; + + return strstr.str(); +} + +class TextureSamplingBenchmark : public ANGLERenderTest, + public ::testing::WithParamInterface<TextureSamplingParams> +{ + public: + TextureSamplingBenchmark(); + + void initializeBenchmark() override; + void destroyBenchmark() override; + void drawBenchmark() override; + + private: + void initShaders(); + void initVertexBuffer(); + void initTextures(); + + GLuint mProgram; + GLuint mBuffer; + std::vector<GLuint> mTextures; +}; + +TextureSamplingBenchmark::TextureSamplingBenchmark() + : ANGLERenderTest("TextureSampling", GetParam()), mProgram(0u), mBuffer(0u) +{ +} + +void TextureSamplingBenchmark::initializeBenchmark() +{ + const auto ¶ms = GetParam(); + + ASSERT_LT(0u, params.iterations); + + // Verify "numSamplers" is within MAX_TEXTURE_IMAGE_UNITS limit + GLint maxTextureImageUnits; + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits); + + if (params.numSamplers > static_cast<unsigned int>(maxTextureImageUnits)) + { + FAIL() << "Sampler count (" << params.numSamplers << ")" + << " exceeds maximum texture count: " << maxTextureImageUnits << std::endl; + } + initShaders(); + initVertexBuffer(); + initTextures(); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight()); + + ASSERT_GL_NO_ERROR(); +} + +void TextureSamplingBenchmark::initShaders() +{ + const auto ¶ms = GetParam(); + + std::stringstream vstrstr; + vstrstr << "attribute vec2 aPosition;\n" + "varying vec2 vTextureCoordinates;\n" + "void main()\n" + "{\n" + " vTextureCoordinates = (aPosition + vec2(1.0)) * 0.5;\n" + " gl_Position = vec4(aPosition, 0, 1.0);\n" + "}"; + + std::stringstream fstrstr; + fstrstr << "precision mediump float;\n" + "varying vec2 vTextureCoordinates;\n"; + for (unsigned int count = 0; count < params.numSamplers; count++) + { + fstrstr << "uniform sampler2D uSampler" << count << ";\n"; + } + fstrstr << "void main()\n" + "{\n" + " const float inverseTextureSize = 1.0 / " + << params.textureSize << ".0;\n" + " vec4 colorOut = vec4(0.0, 0.0, 0.0, 1.0);\n"; + for (unsigned int count = 0; count < params.numSamplers; count++) + { + fstrstr << " for (int x = 0; x < " << params.kernelSize << "; ++x)\n" + " {\n" + " for (int y = 0; y < " << params.kernelSize << "; ++y)\n" + " {\n" + " colorOut += texture2D(uSampler" << count + << ", vTextureCoordinates + vec2(x, y) * inverseTextureSize) * 0.1;\n" + " }\n" + " }\n"; + } + fstrstr << " gl_FragColor = colorOut;\n" + "}\n"; + + mProgram = CompileProgram(vstrstr.str(), fstrstr.str()); + ASSERT_NE(0u, mProgram); + + // Use the program object + glUseProgram(mProgram); +} + +void TextureSamplingBenchmark::initVertexBuffer() +{ + std::vector<float> vertexPositions(12); + { + // Bottom left triangle + vertexPositions[0] = -1.0f; + vertexPositions[1] = -1.0f; + vertexPositions[2] = 1.0f; + vertexPositions[3] = -1.0f; + vertexPositions[4] = -1.0f; + vertexPositions[5] = 1.0f; + + // Top right triangle + vertexPositions[6] = -1.0f; + vertexPositions[7] = 1.0f; + vertexPositions[8] = 1.0f; + vertexPositions[9] = -1.0f; + vertexPositions[10] = 1.0f; + vertexPositions[11] = 1.0f; + } + + glGenBuffers(1, &mBuffer); + glBindBuffer(GL_ARRAY_BUFFER, mBuffer); + glBufferData(GL_ARRAY_BUFFER, vertexPositions.size() * sizeof(float), &vertexPositions[0], + GL_STATIC_DRAW); + + GLint positionLocation = glGetAttribLocation(mProgram, "aPosition"); + ASSERT_NE(-1, positionLocation); + + glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, nullptr); + glEnableVertexAttribArray(positionLocation); +} + +void TextureSamplingBenchmark::initTextures() +{ + const auto ¶ms = GetParam(); + + unsigned int dataSize = params.textureSize * params.textureSize; + std::vector<unsigned int> randomTextureData; + randomTextureData.resize(dataSize); + + unsigned int pseudoRandom = 1u; + for (unsigned int i = 0; i < dataSize; ++i) + { + pseudoRandom = pseudoRandom * 1664525u + 1013904223u; + randomTextureData[i] = pseudoRandom; + } + + mTextures.resize(params.numSamplers); + glGenTextures(params.numSamplers, mTextures.data()); + for (unsigned int i = 0; i < params.numSamplers; ++i) + { + glActiveTexture(GL_TEXTURE0 + i); + glBindTexture(GL_TEXTURE_2D, mTextures[i]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, params.textureSize, params.textureSize, 0, GL_RGBA, + GL_UNSIGNED_BYTE, randomTextureData.data()); + } + + for (unsigned int count = 0; count < params.numSamplers; count++) + { + std::stringstream samplerstrstr; + samplerstrstr << "uSampler" << count; + GLint samplerLocation = glGetUniformLocation(mProgram, samplerstrstr.str().c_str()); + ASSERT_NE(-1, samplerLocation); + + glUniform1i(samplerLocation, count); + } +} + +void TextureSamplingBenchmark::destroyBenchmark() +{ + const auto ¶ms = GetParam(); + + glDeleteProgram(mProgram); + glDeleteBuffers(1, &mBuffer); + if (!mTextures.empty()) + { + glDeleteTextures(params.numSamplers, mTextures.data()); + } +} + +void TextureSamplingBenchmark::drawBenchmark() +{ + glClear(GL_COLOR_BUFFER_BIT); + + const auto ¶ms = GetParam(); + + for (unsigned int it = 0; it < params.iterations; ++it) + { + glDrawArrays(GL_TRIANGLES, 0, 6); + } + + ASSERT_GL_NO_ERROR(); +} + +TextureSamplingParams D3D11Params() +{ + TextureSamplingParams params; + params.eglParameters = egl_platform::D3D11(); + return params; +} + +TextureSamplingParams D3D9Params() +{ + TextureSamplingParams params; + params.eglParameters = egl_platform::D3D9(); + return params; +} + +TextureSamplingParams OpenGLParams() +{ + TextureSamplingParams params; + params.eglParameters = egl_platform::OPENGL(); + return params; +} + +} // anonymous namespace + +TEST_P(TextureSamplingBenchmark, Run) +{ + run(); +} + +ANGLE_INSTANTIATE_TEST(TextureSamplingBenchmark, D3D11Params(), D3D9Params(), OpenGLParams()); |