summaryrefslogtreecommitdiffstats
path: root/gfx/angle/src/tests/perf_tests/IndexConversionPerf.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/src/tests/perf_tests/IndexConversionPerf.cpp')
-rwxr-xr-xgfx/angle/src/tests/perf_tests/IndexConversionPerf.cpp271
1 files changed, 271 insertions, 0 deletions
diff --git a/gfx/angle/src/tests/perf_tests/IndexConversionPerf.cpp b/gfx/angle/src/tests/perf_tests/IndexConversionPerf.cpp
new file mode 100755
index 000000000..d05e79d09
--- /dev/null
+++ b/gfx/angle/src/tests/perf_tests/IndexConversionPerf.cpp
@@ -0,0 +1,271 @@
+//
+// Copyright 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.
+//
+// IndexConversionPerf:
+// Performance tests for ANGLE index conversion in D3D11.
+//
+
+#include <sstream>
+
+#include "ANGLEPerfTest.h"
+#include "shader_utils.h"
+
+using namespace angle;
+
+namespace
+{
+
+struct IndexConversionPerfParams final : public RenderTestParams
+{
+ std::string suffix() const override
+ {
+ std::stringstream strstr;
+
+ if (indexRangeOffset > 0)
+ {
+ strstr << "_index_range";
+ }
+
+ strstr << RenderTestParams::suffix();
+
+ return strstr.str();
+ }
+
+ unsigned int iterations;
+ unsigned int numIndexTris;
+
+ // A second test, which covers using index ranges with an offset.
+ unsigned int indexRangeOffset;
+};
+
+// Provide a custom gtest parameter name function for IndexConversionPerfParams.
+std::ostream &operator<<(std::ostream &stream, const IndexConversionPerfParams &param)
+{
+ stream << param.suffix().substr(1);
+ return stream;
+}
+
+class IndexConversionPerfTest : public ANGLERenderTest,
+ public ::testing::WithParamInterface<IndexConversionPerfParams>
+{
+ public:
+ IndexConversionPerfTest();
+
+ void initializeBenchmark() override;
+ void destroyBenchmark() override;
+ void drawBenchmark() override;
+
+ private:
+ void updateBufferData();
+ void drawConversion();
+ void drawIndexRange();
+
+ GLuint mProgram;
+ GLuint mVertexBuffer;
+ GLuint mIndexBuffer;
+ std::vector<GLushort> mIndexData;
+};
+
+IndexConversionPerfTest::IndexConversionPerfTest()
+ : ANGLERenderTest("IndexConversionPerfTest", GetParam()),
+ mProgram(0),
+ mVertexBuffer(0),
+ mIndexBuffer(0)
+{
+ mRunTimeSeconds = 3.0;
+}
+
+void IndexConversionPerfTest::initializeBenchmark()
+{
+ const auto &params = GetParam();
+
+ ASSERT_LT(0u, params.iterations);
+ ASSERT_LT(0u, params.numIndexTris);
+
+ const std::string vs = SHADER_SOURCE
+ (
+ attribute vec2 vPosition;
+ uniform float uScale;
+ uniform float uOffset;
+ void main()
+ {
+ gl_Position = vec4(vPosition * vec2(uScale) - vec2(uOffset), 0, 1);
+ }
+ );
+
+ const std::string fs = SHADER_SOURCE
+ (
+ precision mediump float;
+ void main()
+ {
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+ }
+ );
+
+ mProgram = CompileProgram(vs, fs);
+ ASSERT_NE(0u, mProgram);
+
+ // Use the program object
+ glUseProgram(mProgram);
+
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+ // Initialize the vertex data
+ std::vector<GLfloat> floatData;
+
+ size_t numTris = std::numeric_limits<GLushort>::max() / 3 + 1;
+ for (size_t triIndex = 0; triIndex < numTris; ++triIndex)
+ {
+ floatData.push_back(1);
+ floatData.push_back(2);
+ floatData.push_back(0);
+ floatData.push_back(0);
+ floatData.push_back(2);
+ floatData.push_back(0);
+ }
+
+ glGenBuffers(1, &mVertexBuffer);
+ glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
+ glBufferData(GL_ARRAY_BUFFER, floatData.size() * sizeof(GLfloat), &floatData[0], GL_STATIC_DRAW);
+
+ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
+ glEnableVertexAttribArray(0);
+
+ // Initialize the index buffer
+ for (unsigned int triIndex = 0; triIndex < params.numIndexTris; ++triIndex)
+ {
+ // Handle two different types of tests, one with index conversion triggered by a -1 index.
+ if (params.indexRangeOffset == 0)
+ {
+ mIndexData.push_back(std::numeric_limits<GLushort>::max());
+ }
+ else
+ {
+ mIndexData.push_back(0);
+ }
+
+ mIndexData.push_back(1);
+ mIndexData.push_back(2);
+ }
+
+ glGenBuffers(1, &mIndexBuffer);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
+ updateBufferData();
+
+ // Set the viewport
+ glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
+
+ GLfloat scale = 0.5f;
+ GLfloat offset = 0.5f;
+
+ glUniform1f(glGetUniformLocation(mProgram, "uScale"), scale);
+ glUniform1f(glGetUniformLocation(mProgram, "uOffset"), offset);
+
+ ASSERT_GL_NO_ERROR();
+}
+
+void IndexConversionPerfTest::updateBufferData()
+{
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, mIndexData.size() * sizeof(mIndexData[0]), &mIndexData[0], GL_STATIC_DRAW);
+}
+
+void IndexConversionPerfTest::destroyBenchmark()
+{
+ glDeleteProgram(mProgram);
+ glDeleteBuffers(1, &mVertexBuffer);
+ glDeleteBuffers(1, &mIndexBuffer);
+}
+
+void IndexConversionPerfTest::drawBenchmark()
+{
+ const auto &params = GetParam();
+
+ if (params.indexRangeOffset == 0)
+ {
+ drawConversion();
+ }
+ else
+ {
+ drawIndexRange();
+ }
+}
+
+void IndexConversionPerfTest::drawConversion()
+{
+ const auto &params = GetParam();
+
+ // Trigger an update to ensure we convert once a frame
+ updateBufferData();
+
+ for (unsigned int it = 0; it < params.iterations; it++)
+ {
+ glDrawElements(GL_TRIANGLES,
+ static_cast<GLsizei>(params.numIndexTris * 3 - 1),
+ GL_UNSIGNED_SHORT,
+ reinterpret_cast<GLvoid*>(0));
+ }
+
+ ASSERT_GL_NO_ERROR();
+}
+
+void IndexConversionPerfTest::drawIndexRange()
+{
+ const auto &params = GetParam();
+
+ unsigned int indexCount = 3;
+ size_t offset = static_cast<size_t>(indexCount * getNumStepsPerformed());
+
+ offset %= (params.numIndexTris * 3);
+
+ // This test increments an offset each step. Drawing repeatedly may cause the system memory
+ // to release. Then, using a fresh offset will require index range validation, which pages
+ // it back in. The performance should be good even if the data is was used quite a bit.
+ for (unsigned int it = 0; it < params.iterations; it++)
+ {
+ glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(indexCount), GL_UNSIGNED_SHORT,
+ reinterpret_cast<GLvoid *>(offset));
+ }
+
+ ASSERT_GL_NO_ERROR();
+}
+
+IndexConversionPerfParams IndexConversionPerfD3D11Params()
+{
+ IndexConversionPerfParams params;
+ params.eglParameters = egl_platform::D3D11_NULL();
+ params.majorVersion = 2;
+ params.minorVersion = 0;
+ params.windowWidth = 256;
+ params.windowHeight = 256;
+ params.iterations = 225;
+ params.numIndexTris = 3000;
+ params.indexRangeOffset = 0;
+ return params;
+}
+
+IndexConversionPerfParams IndexRangeOffsetPerfD3D11Params()
+{
+ IndexConversionPerfParams params;
+ params.eglParameters = egl_platform::D3D11_NULL();
+ params.majorVersion = 2;
+ params.minorVersion = 0;
+ params.windowWidth = 256;
+ params.windowHeight = 256;
+ params.iterations = 16;
+ params.numIndexTris = 50000;
+ params.indexRangeOffset = 64;
+ return params;
+}
+
+TEST_P(IndexConversionPerfTest, Run)
+{
+ run();
+}
+
+ANGLE_INSTANTIATE_TEST(IndexConversionPerfTest,
+ IndexConversionPerfD3D11Params(),
+ IndexRangeOffsetPerfD3D11Params());
+
+} // namespace