Commit 232bfeae by Shahbaz Youssefi Committed by Commit Bot

Add perf test for texture upload gpu time

This perf test measures the GPU time spent uploading texture data. Bug: angleproject:2361 Change-Id: I62fcf0e893fdcc9826a083e23320051a69559fab Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1529922 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent cf8735dc
...@@ -24,8 +24,8 @@ angle_perf_tests_sources = [ ...@@ -24,8 +24,8 @@ angle_perf_tests_sources = [
"perf_tests/LinkProgramPerfTest.cpp", "perf_tests/LinkProgramPerfTest.cpp",
"perf_tests/MultiviewPerf.cpp", "perf_tests/MultiviewPerf.cpp",
"perf_tests/PointSprites.cpp", "perf_tests/PointSprites.cpp",
"perf_tests/TexSubImage.cpp",
"perf_tests/TextureSampling.cpp", "perf_tests/TextureSampling.cpp",
"perf_tests/TextureUploadPerf.cpp",
"perf_tests/TexturesPerf.cpp", "perf_tests/TexturesPerf.cpp",
"perf_tests/UniformsPerf.cpp", "perf_tests/UniformsPerf.cpp",
"perf_tests/VulkanBarriersPerf.cpp", "perf_tests/VulkanBarriersPerf.cpp",
......
//
// Copyright (c) 2014 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.
//
// TexSubImageBenchmark:
// Performace test for ANGLE texture updates.
//
#include <sstream>
#include "ANGLEPerfTest.h"
#include "util/shader_utils.h"
using namespace angle;
namespace
{
constexpr unsigned int kIterationsPerStep = 9;
struct TexSubImageParams final : public RenderTestParams
{
TexSubImageParams()
{
iterationsPerStep = kIterationsPerStep;
// Common default parameters
majorVersion = 2;
minorVersion = 0;
windowWidth = 512;
windowHeight = 512;
imageWidth = 1024;
imageHeight = 1024;
subImageWidth = 64;
subImageHeight = 64;
}
std::string suffix() const override;
// Static parameters
int imageWidth;
int imageHeight;
int subImageWidth;
int subImageHeight;
};
std::ostream &operator<<(std::ostream &os, const TexSubImageParams &params)
{
os << params.suffix().substr(1);
return os;
}
class TexSubImageBenchmark : public ANGLERenderTest,
public ::testing::WithParamInterface<TexSubImageParams>
{
public:
TexSubImageBenchmark();
void initializeBenchmark() override;
void destroyBenchmark() override;
void drawBenchmark() override;
private:
GLuint createTexture();
// Handle to a program object
GLuint mProgram;
// Attribute locations
GLint mPositionLoc;
GLint mTexCoordLoc;
// Sampler location
GLint mSamplerLoc;
// Texture handle
GLuint mTexture;
// Buffer handle
GLuint mVertexBuffer;
GLuint mIndexBuffer;
GLubyte *mPixels;
};
std::string TexSubImageParams::suffix() const
{
// TODO(jmadill)
return RenderTestParams::suffix();
}
TexSubImageBenchmark::TexSubImageBenchmark()
: ANGLERenderTest("TexSubImage", GetParam()),
mProgram(0),
mPositionLoc(-1),
mTexCoordLoc(-1),
mSamplerLoc(-1),
mTexture(0),
mVertexBuffer(0),
mIndexBuffer(0),
mPixels(nullptr)
{
addExtensionPrerequisite("GL_EXT_texture_storage");
}
GLuint TexSubImageBenchmark::createTexture()
{
const auto &params = GetParam();
// Use tightly packed data
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Generate a texture object
GLuint texture;
glGenTextures(1, &texture);
// Bind the texture object
glBindTexture(GL_TEXTURE_2D, texture);
glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, params.imageWidth, params.imageHeight);
// Set the filtering mode
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
return texture;
}
void TexSubImageBenchmark::initializeBenchmark()
{
const auto &params = GetParam();
constexpr char kVS[] = R"(attribute vec4 a_position;
attribute vec2 a_texCoord;
varying vec2 v_texCoord;
void main()
{
gl_Position = a_position;
v_texCoord = a_texCoord;
})";
constexpr char kFS[] = R"(precision mediump float;
varying vec2 v_texCoord;
uniform sampler2D s_texture;
void main()
{
gl_FragColor = texture2D(s_texture, v_texCoord);
})";
mProgram = CompileProgram(kVS, kFS);
ASSERT_NE(0u, mProgram);
// Get the attribute locations
mPositionLoc = glGetAttribLocation(mProgram, "a_position");
mTexCoordLoc = glGetAttribLocation(mProgram, "a_texCoord");
// Get the sampler location
mSamplerLoc = glGetUniformLocation(mProgram, "s_texture");
// Build the vertex buffer
GLfloat vertices[] = {
-0.5f, 0.5f, 0.0f, // Position 0
0.0f, 0.0f, // TexCoord 0
-0.5f, -0.5f, 0.0f, // Position 1
0.0f, 1.0f, // TexCoord 1
0.5f, -0.5f, 0.0f, // Position 2
1.0f, 1.0f, // TexCoord 2
0.5f, 0.5f, 0.0f, // Position 3
1.0f, 0.0f // TexCoord 3
};
glGenBuffers(1, &mVertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
GLushort indices[] = {0, 1, 2, 0, 2, 3};
glGenBuffers(1, &mIndexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// Load the texture
mTexture = createTexture();
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
mPixels = new GLubyte[params.subImageWidth * params.subImageHeight * 4];
// Fill the pixels structure with random data:
for (int y = 0; y < params.subImageHeight; ++y)
{
for (int x = 0; x < params.subImageWidth; ++x)
{
int offset = (x + (y * params.subImageWidth)) * 4;
mPixels[offset + 0] = rand() % 255; // Red
mPixels[offset + 1] = rand() % 255; // Green
mPixels[offset + 2] = rand() % 255; // Blue
mPixels[offset + 3] = 255; // Alpha
}
}
ASSERT_GL_NO_ERROR();
}
void TexSubImageBenchmark::destroyBenchmark()
{
glDeleteProgram(mProgram);
glDeleteBuffers(1, &mVertexBuffer);
glDeleteBuffers(1, &mIndexBuffer);
glDeleteTextures(1, &mTexture);
delete[] mPixels;
}
void TexSubImageBenchmark::drawBenchmark()
{
// Set the viewport
glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
// Clear the color buffer
glClear(GL_COLOR_BUFFER_BIT);
// Use the program object
glUseProgram(mProgram);
// Bind the buffers
glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
// Load the vertex position
glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 0);
// Load the texture coordinate
glVertexAttribPointer(mTexCoordLoc, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat),
reinterpret_cast<void *>(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(mPositionLoc);
glEnableVertexAttribArray(mTexCoordLoc);
// Bind the texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mTexture);
// Set the texture sampler to texture unit to 0
glUniform1i(mSamplerLoc, 0);
ASSERT_GL_NO_ERROR();
const auto &params = GetParam();
for (unsigned int iteration = 0; iteration < params.iterationsPerStep; ++iteration)
{
glTexSubImage2D(GL_TEXTURE_2D, 0, rand() % (params.imageWidth - params.subImageWidth),
rand() % (params.imageHeight - params.subImageHeight), params.subImageWidth,
params.subImageHeight, GL_RGBA, GL_UNSIGNED_BYTE, mPixels);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
}
ASSERT_GL_NO_ERROR();
}
TexSubImageParams D3D11Params()
{
TexSubImageParams params;
params.eglParameters = egl_platform::D3D11();
return params;
}
TexSubImageParams D3D9Params()
{
TexSubImageParams params;
params.eglParameters = egl_platform::D3D9();
return params;
}
TexSubImageParams OpenGLOrGLESParams()
{
TexSubImageParams params;
params.eglParameters = egl_platform::OPENGL_OR_GLES(false);
return params;
}
TexSubImageParams VulkanParams()
{
TexSubImageParams params;
params.eglParameters = egl_platform::VULKAN();
return params;
}
} // namespace
TEST_P(TexSubImageBenchmark, Run)
{
run();
}
ANGLE_INSTANTIATE_TEST(TexSubImageBenchmark,
D3D11Params(),
D3D9Params(),
OpenGLOrGLESParams(),
VulkanParams());
//
// Copyright 2019 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.
//
// TextureUploadBenchmark:
// Performance test for uploading texture data.
//
#include "ANGLEPerfTest.h"
#include <iostream>
#include <random>
#include <sstream>
#include "test_utils/gl_raii.h"
#include "util/shader_utils.h"
namespace angle
{
constexpr unsigned int kIterationsPerStep = 64;
struct TextureUploadParams final : public RenderTestParams
{
TextureUploadParams()
{
iterationsPerStep = kIterationsPerStep;
trackGpuTime = true;
baseSize = 2048;
subImageSize = 64;
webgl = false;
}
std::string suffix() const override;
GLsizei baseSize;
GLsizei subImageSize;
bool webgl;
};
std::ostream &operator<<(std::ostream &os, const TextureUploadParams &params)
{
os << params.suffix().substr(1);
return os;
}
std::string TextureUploadParams::suffix() const
{
std::stringstream strstr;
strstr << RenderTestParams::suffix();
if (webgl)
{
strstr << "_webgl";
}
return strstr.str();
}
class TextureUploadBenchmarkBase : public ANGLERenderTest,
public ::testing::WithParamInterface<TextureUploadParams>
{
public:
TextureUploadBenchmarkBase(const char *benchmarkName);
void initializeBenchmark() override;
void destroyBenchmark() override;
protected:
void initShaders();
GLuint mProgram;
GLuint mPositionLoc;
GLuint mSamplerLoc;
};
class TextureUploadSubImageBenchmark : public TextureUploadBenchmarkBase
{
public:
TextureUploadSubImageBenchmark() : TextureUploadBenchmarkBase("TexSubImage")
{
addExtensionPrerequisite("GL_EXT_texture_storage");
}
void drawBenchmark() override;
};
class TextureUploadFullMipBenchmark : public TextureUploadBenchmarkBase
{
public:
TextureUploadFullMipBenchmark() : TextureUploadBenchmarkBase("TextureUpload") {}
void drawBenchmark() override;
};
TextureUploadBenchmarkBase::TextureUploadBenchmarkBase(const char *benchmarkName)
: ANGLERenderTest(benchmarkName, GetParam()), mProgram(0u), mPositionLoc(-1), mSamplerLoc(-1)
{
setWebGLCompatibilityEnabled(GetParam().webgl);
setRobustResourceInit(GetParam().webgl);
}
void TextureUploadBenchmarkBase::initializeBenchmark()
{
const auto &params = GetParam();
initShaders();
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
if (params.webgl)
{
glRequestExtensionANGLE("GL_EXT_disjoint_timer_query");
}
ASSERT_GL_NO_ERROR();
}
void TextureUploadBenchmarkBase::initShaders()
{
constexpr char kVS[] = R"(attribute vec4 a_position;
void main()
{
gl_Position = a_position;
})";
constexpr char kFS[] = R"(precision mediump float;
uniform sampler2D s_texture;
void main()
{
gl_FragColor = texture2D(s_texture, vec2(0, 0));
})";
mProgram = CompileProgram(kVS, kFS);
ASSERT_NE(0u, mProgram);
mPositionLoc = glGetAttribLocation(mProgram, "a_position");
mSamplerLoc = glGetUniformLocation(mProgram, "s_texture");
glUseProgram(mProgram);
glDisable(GL_DEPTH_TEST);
ASSERT_GL_NO_ERROR();
}
void TextureUploadBenchmarkBase::destroyBenchmark()
{
glDeleteProgram(mProgram);
}
void TextureUploadSubImageBenchmark::drawBenchmark()
{
const auto &params = GetParam();
std::vector<float> textureData(params.subImageSize * params.subImageSize * 4, 0.5);
GLTexture tex;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex);
glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, params.baseSize, params.baseSize);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glUniform1i(mSamplerLoc, 0);
ASSERT_GL_NO_ERROR();
startGpuTimer();
for (unsigned int iteration = 0; iteration < params.iterationsPerStep; ++iteration)
{
glTexSubImage2D(GL_TEXTURE_2D, 0, rand() % (params.baseSize - params.subImageSize),
rand() % (params.baseSize - params.subImageSize), params.subImageSize,
params.subImageSize, GL_RGBA, GL_UNSIGNED_BYTE, textureData.data());
// Perform a draw just so the texture data is flushed. With the position attributes not
// set, a constant default value is used, resulting in a very cheap draw.
glDrawArrays(GL_TRIANGLES, 0, 3);
}
stopGpuTimer();
ASSERT_GL_NO_ERROR();
}
void TextureUploadFullMipBenchmark::drawBenchmark()
{
const auto &params = GetParam();
std::vector<float> textureData(params.baseSize * params.baseSize * 4, 0.5);
startGpuTimer();
for (size_t it = 0; it < params.iterationsPerStep; ++it)
{
GLTexture tex;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex);
// Stage data for all mips
GLint mip = 0;
for (GLsizei levelSize = params.baseSize; levelSize > 0; levelSize >>= 1)
{
glTexImage2D(GL_TEXTURE_2D, mip++, GL_RGBA, levelSize, levelSize, 0, GL_RGBA,
GL_UNSIGNED_BYTE, textureData.data());
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glUniform1i(mSamplerLoc, 0);
// Perform a draw just so the texture data is flushed. With the position attributes not
// set, a constant default value is used, resulting in a very cheap draw.
glDrawArrays(GL_TRIANGLES, 0, 3);
}
stopGpuTimer();
ASSERT_GL_NO_ERROR();
}
TextureUploadParams TextureUploadD3D11Params(bool webglCompat)
{
TextureUploadParams params;
params.eglParameters = egl_platform::D3D11();
params.webgl = webglCompat;
return params;
}
TextureUploadParams TextureUploadOpenGLOrGLESParams(bool webglCompat)
{
TextureUploadParams params;
params.eglParameters = egl_platform::OPENGL_OR_GLES(false);
params.webgl = webglCompat;
return params;
}
TextureUploadParams TextureUploadVulkanParams(bool webglCompat)
{
TextureUploadParams params;
params.eglParameters = egl_platform::VULKAN();
params.webgl = webglCompat;
return params;
}
TEST_P(TextureUploadSubImageBenchmark, Run)
{
run();
}
TEST_P(TextureUploadFullMipBenchmark, Run)
{
run();
}
ANGLE_INSTANTIATE_TEST(TextureUploadSubImageBenchmark,
TextureUploadD3D11Params(false),
TextureUploadD3D11Params(true),
TextureUploadOpenGLOrGLESParams(false),
TextureUploadOpenGLOrGLESParams(true),
TextureUploadVulkanParams(false),
TextureUploadVulkanParams(true));
ANGLE_INSTANTIATE_TEST(TextureUploadFullMipBenchmark,
TextureUploadD3D11Params(false),
TextureUploadD3D11Params(true),
TextureUploadOpenGLOrGLESParams(false),
TextureUploadOpenGLOrGLESParams(true),
TextureUploadVulkanParams(false),
TextureUploadVulkanParams(true));
} // namespace angle
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment