blob: 3cfda288207faf75ef915024a82ce8816eee350a [file] [log] [blame]
//
// Copyright 2016 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.
//
// DynamicPromotionPerfTest:
// Tests that ANGLE will promote buffer specfied with DYNAMIC usage to static after a number of
// iterations without changing the data. It specifically affects the D3D back-end, which treats
// dynamic and static buffers quite differently.
//
#include "ANGLEPerfTest.h"
#include "common/vector_utils.h"
#include "util/random_utils.h"
#include "util/shader_utils.h"
using namespace angle;
namespace
{
constexpr unsigned int kIterationsPerStep = 4;
struct DynamicPromotionParams final : public RenderTestParams
{
DynamicPromotionParams() { iterationsPerStep = kIterationsPerStep; }
std::string story() const override;
size_t vertexCount = 1024;
};
std::string DynamicPromotionParams::story() const
{
return RenderTestParams::story();
}
std::ostream &operator<<(std::ostream &os, const DynamicPromotionParams &params)
{
os << params.backendAndStory().substr(1);
return os;
}
class DynamicPromotionPerfTest : public ANGLERenderTest,
public testing::WithParamInterface<DynamicPromotionParams>
{
public:
DynamicPromotionPerfTest();
void initializeBenchmark() override;
void destroyBenchmark() override;
void drawBenchmark() override;
private:
GLuint mProgram;
GLuint mElementArrayBuffer;
GLuint mArrayBuffer;
};
DynamicPromotionPerfTest::DynamicPromotionPerfTest()
: ANGLERenderTest("DynamicPromotion", GetParam()),
mProgram(0),
mElementArrayBuffer(0),
mArrayBuffer(0)
{}
void DynamicPromotionPerfTest::initializeBenchmark()
{
constexpr char kVertexShaderSource[] =
"attribute vec2 position;\n"
"attribute vec3 color;\n"
"varying vec3 vColor;\n"
"void main()\n"
"{\n"
" vColor = color;\n"
" gl_Position = vec4(position, 0, 1);\n"
"}";
constexpr char kFragmentShaderSource[] =
"varying mediump vec3 vColor;\n"
"void main()\n"
"{\n"
" gl_FragColor = vec4(vColor, 1);\n"
"}";
mProgram = CompileProgram(kVertexShaderSource, kFragmentShaderSource);
ASSERT_NE(0u, mProgram);
const size_t vertexCount = GetParam().vertexCount;
std::vector<GLushort> indexData;
std::vector<Vector2> positionData;
std::vector<Vector3> colorData;
ASSERT_GE(static_cast<size_t>(std::numeric_limits<GLushort>::max()), vertexCount);
RNG rng(1);
for (size_t index = 0; index < vertexCount; ++index)
{
indexData.push_back(static_cast<GLushort>(index));
Vector2 position(rng.randomNegativeOneToOne(), rng.randomNegativeOneToOne());
positionData.push_back(position);
Vector3 color(rng.randomFloat(), rng.randomFloat(), rng.randomFloat());
colorData.push_back(color);
}
glGenBuffers(1, &mElementArrayBuffer);
glGenBuffers(1, &mArrayBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mElementArrayBuffer);
glBindBuffer(GL_ARRAY_BUFFER, mArrayBuffer);
GLsizeiptr elementArraySize = sizeof(GLushort) * vertexCount;
GLsizeiptr positionArraySize = sizeof(Vector2) * vertexCount;
GLsizeiptr colorArraySize = sizeof(Vector3) * vertexCount;
// The DYNAMIC_DRAW usage is the key to the test.
glBufferData(GL_ELEMENT_ARRAY_BUFFER, elementArraySize, indexData.data(), GL_DYNAMIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, positionArraySize + colorArraySize, nullptr, GL_DYNAMIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, positionArraySize, positionData.data());
glBufferSubData(GL_ARRAY_BUFFER, positionArraySize, colorArraySize, colorData.data());
glUseProgram(mProgram);
GLint positionLocation = glGetAttribLocation(mProgram, "position");
ASSERT_NE(-1, positionLocation);
GLint colorLocation = glGetAttribLocation(mProgram, "color");
ASSERT_NE(-1, colorLocation);
glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
glVertexAttribPointer(colorLocation, 3, GL_FLOAT, GL_FALSE, 0,
reinterpret_cast<const void *>(positionArraySize));
glEnableVertexAttribArray(positionLocation);
glEnableVertexAttribArray(colorLocation);
ASSERT_GL_NO_ERROR();
}
void DynamicPromotionPerfTest::destroyBenchmark()
{
glDeleteProgram(mProgram);
glDeleteBuffers(1, &mElementArrayBuffer);
glDeleteBuffers(1, &mArrayBuffer);
}
void DynamicPromotionPerfTest::drawBenchmark()
{
unsigned int iterations = GetParam().iterationsPerStep;
size_t vertexCount = GetParam().vertexCount;
glClear(GL_COLOR_BUFFER_BIT);
for (unsigned int count = 0; count < iterations; ++count)
{
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(vertexCount), GL_UNSIGNED_SHORT, nullptr);
}
ASSERT_GL_NO_ERROR();
}
DynamicPromotionParams DynamicPromotionD3D11Params()
{
DynamicPromotionParams params;
params.eglParameters = egl_platform::D3D11();
return params;
}
DynamicPromotionParams DynamicPromotionD3D9Params()
{
DynamicPromotionParams params;
params.eglParameters = egl_platform::D3D9();
return params;
}
TEST_P(DynamicPromotionPerfTest, Run)
{
run();
}
ANGLE_INSTANTIATE_TEST(DynamicPromotionPerfTest,
DynamicPromotionD3D11Params(),
DynamicPromotionD3D9Params());
} // anonymous namespace