1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2017 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker // DrawElementsPerf:
7*8975f5c5SAndroid Build Coastguard Worker // Performance tests for ANGLE DrawElements call overhead.
8*8975f5c5SAndroid Build Coastguard Worker //
9*8975f5c5SAndroid Build Coastguard Worker
10*8975f5c5SAndroid Build Coastguard Worker #include <sstream>
11*8975f5c5SAndroid Build Coastguard Worker
12*8975f5c5SAndroid Build Coastguard Worker #include "ANGLEPerfTest.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "DrawCallPerfParams.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "test_utils/draw_call_perf_utils.h"
15*8975f5c5SAndroid Build Coastguard Worker
16*8975f5c5SAndroid Build Coastguard Worker namespace
17*8975f5c5SAndroid Build Coastguard Worker {
18*8975f5c5SAndroid Build Coastguard Worker
CreateElementArrayBuffer(size_t count,GLenum type,GLenum usage)19*8975f5c5SAndroid Build Coastguard Worker GLuint CreateElementArrayBuffer(size_t count, GLenum type, GLenum usage)
20*8975f5c5SAndroid Build Coastguard Worker {
21*8975f5c5SAndroid Build Coastguard Worker GLuint buffer = 0u;
22*8975f5c5SAndroid Build Coastguard Worker glGenBuffers(1, &buffer);
23*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
24*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * sizeof(type), nullptr, usage);
25*8975f5c5SAndroid Build Coastguard Worker
26*8975f5c5SAndroid Build Coastguard Worker return buffer;
27*8975f5c5SAndroid Build Coastguard Worker }
28*8975f5c5SAndroid Build Coastguard Worker
29*8975f5c5SAndroid Build Coastguard Worker struct DrawElementsPerfParams final : public DrawCallPerfParams
30*8975f5c5SAndroid Build Coastguard Worker {
31*8975f5c5SAndroid Build Coastguard Worker // Common default options
DrawElementsPerfParams__anon3a1c0d0d0111::DrawElementsPerfParams32*8975f5c5SAndroid Build Coastguard Worker DrawElementsPerfParams()
33*8975f5c5SAndroid Build Coastguard Worker {
34*8975f5c5SAndroid Build Coastguard Worker runTimeSeconds = 5.0;
35*8975f5c5SAndroid Build Coastguard Worker numTris = 2;
36*8975f5c5SAndroid Build Coastguard Worker }
37*8975f5c5SAndroid Build Coastguard Worker
story__anon3a1c0d0d0111::DrawElementsPerfParams38*8975f5c5SAndroid Build Coastguard Worker std::string story() const override
39*8975f5c5SAndroid Build Coastguard Worker {
40*8975f5c5SAndroid Build Coastguard Worker std::stringstream strstr;
41*8975f5c5SAndroid Build Coastguard Worker
42*8975f5c5SAndroid Build Coastguard Worker strstr << DrawCallPerfParams::story();
43*8975f5c5SAndroid Build Coastguard Worker
44*8975f5c5SAndroid Build Coastguard Worker if (indexBufferChanged)
45*8975f5c5SAndroid Build Coastguard Worker {
46*8975f5c5SAndroid Build Coastguard Worker strstr << "_index_buffer_changed";
47*8975f5c5SAndroid Build Coastguard Worker }
48*8975f5c5SAndroid Build Coastguard Worker
49*8975f5c5SAndroid Build Coastguard Worker if (type == GL_UNSIGNED_SHORT)
50*8975f5c5SAndroid Build Coastguard Worker {
51*8975f5c5SAndroid Build Coastguard Worker strstr << "_ushort";
52*8975f5c5SAndroid Build Coastguard Worker }
53*8975f5c5SAndroid Build Coastguard Worker
54*8975f5c5SAndroid Build Coastguard Worker return strstr.str();
55*8975f5c5SAndroid Build Coastguard Worker }
56*8975f5c5SAndroid Build Coastguard Worker
57*8975f5c5SAndroid Build Coastguard Worker GLenum type = GL_UNSIGNED_INT;
58*8975f5c5SAndroid Build Coastguard Worker bool indexBufferChanged = false;
59*8975f5c5SAndroid Build Coastguard Worker };
60*8975f5c5SAndroid Build Coastguard Worker
operator <<(std::ostream & os,const DrawElementsPerfParams & params)61*8975f5c5SAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &os, const DrawElementsPerfParams ¶ms)
62*8975f5c5SAndroid Build Coastguard Worker {
63*8975f5c5SAndroid Build Coastguard Worker os << params.backendAndStory().substr(1);
64*8975f5c5SAndroid Build Coastguard Worker return os;
65*8975f5c5SAndroid Build Coastguard Worker }
66*8975f5c5SAndroid Build Coastguard Worker
67*8975f5c5SAndroid Build Coastguard Worker class DrawElementsPerfBenchmark : public ANGLERenderTest,
68*8975f5c5SAndroid Build Coastguard Worker public ::testing::WithParamInterface<DrawElementsPerfParams>
69*8975f5c5SAndroid Build Coastguard Worker {
70*8975f5c5SAndroid Build Coastguard Worker public:
71*8975f5c5SAndroid Build Coastguard Worker DrawElementsPerfBenchmark();
72*8975f5c5SAndroid Build Coastguard Worker
73*8975f5c5SAndroid Build Coastguard Worker void initializeBenchmark() override;
74*8975f5c5SAndroid Build Coastguard Worker void destroyBenchmark() override;
75*8975f5c5SAndroid Build Coastguard Worker void drawBenchmark() override;
76*8975f5c5SAndroid Build Coastguard Worker
77*8975f5c5SAndroid Build Coastguard Worker private:
78*8975f5c5SAndroid Build Coastguard Worker GLuint mProgram = 0;
79*8975f5c5SAndroid Build Coastguard Worker GLuint mBuffer = 0;
80*8975f5c5SAndroid Build Coastguard Worker GLuint mIndexBuffer = 0;
81*8975f5c5SAndroid Build Coastguard Worker GLuint mFBO = 0;
82*8975f5c5SAndroid Build Coastguard Worker GLuint mTexture = 0;
83*8975f5c5SAndroid Build Coastguard Worker GLsizei mBufferSize = 0;
84*8975f5c5SAndroid Build Coastguard Worker int mCount = 3 * GetParam().numTris;
85*8975f5c5SAndroid Build Coastguard Worker std::vector<GLuint> mIntIndexData;
86*8975f5c5SAndroid Build Coastguard Worker std::vector<GLushort> mShortIndexData;
87*8975f5c5SAndroid Build Coastguard Worker };
88*8975f5c5SAndroid Build Coastguard Worker
DrawElementsPerfBenchmark()89*8975f5c5SAndroid Build Coastguard Worker DrawElementsPerfBenchmark::DrawElementsPerfBenchmark()
90*8975f5c5SAndroid Build Coastguard Worker : ANGLERenderTest("DrawElementsPerf", GetParam())
91*8975f5c5SAndroid Build Coastguard Worker {
92*8975f5c5SAndroid Build Coastguard Worker if (GetParam().type == GL_UNSIGNED_INT)
93*8975f5c5SAndroid Build Coastguard Worker {
94*8975f5c5SAndroid Build Coastguard Worker addExtensionPrerequisite("GL_OES_element_index_uint");
95*8975f5c5SAndroid Build Coastguard Worker }
96*8975f5c5SAndroid Build Coastguard Worker }
97*8975f5c5SAndroid Build Coastguard Worker
ElementTypeSize(GLenum elementType)98*8975f5c5SAndroid Build Coastguard Worker GLsizei ElementTypeSize(GLenum elementType)
99*8975f5c5SAndroid Build Coastguard Worker {
100*8975f5c5SAndroid Build Coastguard Worker switch (elementType)
101*8975f5c5SAndroid Build Coastguard Worker {
102*8975f5c5SAndroid Build Coastguard Worker case GL_UNSIGNED_BYTE:
103*8975f5c5SAndroid Build Coastguard Worker return sizeof(GLubyte);
104*8975f5c5SAndroid Build Coastguard Worker case GL_UNSIGNED_SHORT:
105*8975f5c5SAndroid Build Coastguard Worker return sizeof(GLushort);
106*8975f5c5SAndroid Build Coastguard Worker case GL_UNSIGNED_INT:
107*8975f5c5SAndroid Build Coastguard Worker return sizeof(GLuint);
108*8975f5c5SAndroid Build Coastguard Worker default:
109*8975f5c5SAndroid Build Coastguard Worker return 0;
110*8975f5c5SAndroid Build Coastguard Worker }
111*8975f5c5SAndroid Build Coastguard Worker }
112*8975f5c5SAndroid Build Coastguard Worker
initializeBenchmark()113*8975f5c5SAndroid Build Coastguard Worker void DrawElementsPerfBenchmark::initializeBenchmark()
114*8975f5c5SAndroid Build Coastguard Worker {
115*8975f5c5SAndroid Build Coastguard Worker const auto ¶ms = GetParam();
116*8975f5c5SAndroid Build Coastguard Worker
117*8975f5c5SAndroid Build Coastguard Worker mProgram = SetupSimpleDrawProgram();
118*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(0u, mProgram);
119*8975f5c5SAndroid Build Coastguard Worker
120*8975f5c5SAndroid Build Coastguard Worker glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
121*8975f5c5SAndroid Build Coastguard Worker
122*8975f5c5SAndroid Build Coastguard Worker mBuffer = Create2DTriangleBuffer(params.numTris, GL_STATIC_DRAW);
123*8975f5c5SAndroid Build Coastguard Worker mIndexBuffer = CreateElementArrayBuffer(mCount, params.type, GL_STATIC_DRAW);
124*8975f5c5SAndroid Build Coastguard Worker
125*8975f5c5SAndroid Build Coastguard Worker for (int i = 0; i < mCount; i++)
126*8975f5c5SAndroid Build Coastguard Worker {
127*8975f5c5SAndroid Build Coastguard Worker ASSERT_GE(std::numeric_limits<GLushort>::max(), mCount);
128*8975f5c5SAndroid Build Coastguard Worker mShortIndexData.push_back(static_cast<GLushort>(rand() % mCount));
129*8975f5c5SAndroid Build Coastguard Worker mIntIndexData.push_back(rand() % mCount);
130*8975f5c5SAndroid Build Coastguard Worker }
131*8975f5c5SAndroid Build Coastguard Worker
132*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
133*8975f5c5SAndroid Build Coastguard Worker
134*8975f5c5SAndroid Build Coastguard Worker mBufferSize = ElementTypeSize(params.type) * mCount;
135*8975f5c5SAndroid Build Coastguard Worker
136*8975f5c5SAndroid Build Coastguard Worker if (params.type == GL_UNSIGNED_INT)
137*8975f5c5SAndroid Build Coastguard Worker {
138*8975f5c5SAndroid Build Coastguard Worker glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, mBufferSize, mIntIndexData.data());
139*8975f5c5SAndroid Build Coastguard Worker }
140*8975f5c5SAndroid Build Coastguard Worker else
141*8975f5c5SAndroid Build Coastguard Worker {
142*8975f5c5SAndroid Build Coastguard Worker glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, mBufferSize, mShortIndexData.data());
143*8975f5c5SAndroid Build Coastguard Worker }
144*8975f5c5SAndroid Build Coastguard Worker
145*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
146*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(0);
147*8975f5c5SAndroid Build Coastguard Worker
148*8975f5c5SAndroid Build Coastguard Worker // Set the viewport
149*8975f5c5SAndroid Build Coastguard Worker glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
150*8975f5c5SAndroid Build Coastguard Worker
151*8975f5c5SAndroid Build Coastguard Worker if (params.surfaceType == SurfaceType::Offscreen)
152*8975f5c5SAndroid Build Coastguard Worker {
153*8975f5c5SAndroid Build Coastguard Worker CreateColorFBO(getWindow()->getWidth(), getWindow()->getHeight(), &mTexture, &mFBO);
154*8975f5c5SAndroid Build Coastguard Worker }
155*8975f5c5SAndroid Build Coastguard Worker
156*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
157*8975f5c5SAndroid Build Coastguard Worker }
158*8975f5c5SAndroid Build Coastguard Worker
destroyBenchmark()159*8975f5c5SAndroid Build Coastguard Worker void DrawElementsPerfBenchmark::destroyBenchmark()
160*8975f5c5SAndroid Build Coastguard Worker {
161*8975f5c5SAndroid Build Coastguard Worker glDeleteProgram(mProgram);
162*8975f5c5SAndroid Build Coastguard Worker glDeleteBuffers(1, &mBuffer);
163*8975f5c5SAndroid Build Coastguard Worker glDeleteBuffers(1, &mIndexBuffer);
164*8975f5c5SAndroid Build Coastguard Worker glDeleteTextures(1, &mTexture);
165*8975f5c5SAndroid Build Coastguard Worker glDeleteFramebuffers(1, &mFBO);
166*8975f5c5SAndroid Build Coastguard Worker }
167*8975f5c5SAndroid Build Coastguard Worker
drawBenchmark()168*8975f5c5SAndroid Build Coastguard Worker void DrawElementsPerfBenchmark::drawBenchmark()
169*8975f5c5SAndroid Build Coastguard Worker {
170*8975f5c5SAndroid Build Coastguard Worker // This workaround fixes a huge queue of graphics commands accumulating on the GL
171*8975f5c5SAndroid Build Coastguard Worker // back-end. The GL back-end doesn't have a proper NULL device at the moment.
172*8975f5c5SAndroid Build Coastguard Worker // TODO(jmadill): Remove this when/if we ever get a proper OpenGL NULL device.
173*8975f5c5SAndroid Build Coastguard Worker const auto &eglParams = GetParam().eglParameters;
174*8975f5c5SAndroid Build Coastguard Worker if (eglParams.deviceType != EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE ||
175*8975f5c5SAndroid Build Coastguard Worker (eglParams.renderer != EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE &&
176*8975f5c5SAndroid Build Coastguard Worker eglParams.renderer != EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE))
177*8975f5c5SAndroid Build Coastguard Worker {
178*8975f5c5SAndroid Build Coastguard Worker glClear(GL_COLOR_BUFFER_BIT);
179*8975f5c5SAndroid Build Coastguard Worker }
180*8975f5c5SAndroid Build Coastguard Worker
181*8975f5c5SAndroid Build Coastguard Worker const DrawElementsPerfParams ¶ms = GetParam();
182*8975f5c5SAndroid Build Coastguard Worker
183*8975f5c5SAndroid Build Coastguard Worker if (params.indexBufferChanged)
184*8975f5c5SAndroid Build Coastguard Worker {
185*8975f5c5SAndroid Build Coastguard Worker const void *bufferData = (params.type == GL_UNSIGNED_INT)
186*8975f5c5SAndroid Build Coastguard Worker ? static_cast<GLvoid *>(mIntIndexData.data())
187*8975f5c5SAndroid Build Coastguard Worker : static_cast<GLvoid *>(mShortIndexData.data());
188*8975f5c5SAndroid Build Coastguard Worker for (unsigned int it = 0; it < params.iterationsPerStep; it++)
189*8975f5c5SAndroid Build Coastguard Worker {
190*8975f5c5SAndroid Build Coastguard Worker glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, mBufferSize, bufferData);
191*8975f5c5SAndroid Build Coastguard Worker glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(mCount), params.type, 0);
192*8975f5c5SAndroid Build Coastguard Worker }
193*8975f5c5SAndroid Build Coastguard Worker }
194*8975f5c5SAndroid Build Coastguard Worker else
195*8975f5c5SAndroid Build Coastguard Worker {
196*8975f5c5SAndroid Build Coastguard Worker for (unsigned int it = 0; it < params.iterationsPerStep; it++)
197*8975f5c5SAndroid Build Coastguard Worker {
198*8975f5c5SAndroid Build Coastguard Worker glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(mCount), params.type, 0);
199*8975f5c5SAndroid Build Coastguard Worker }
200*8975f5c5SAndroid Build Coastguard Worker }
201*8975f5c5SAndroid Build Coastguard Worker
202*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
203*8975f5c5SAndroid Build Coastguard Worker }
204*8975f5c5SAndroid Build Coastguard Worker
TEST_P(DrawElementsPerfBenchmark,Run)205*8975f5c5SAndroid Build Coastguard Worker TEST_P(DrawElementsPerfBenchmark, Run)
206*8975f5c5SAndroid Build Coastguard Worker {
207*8975f5c5SAndroid Build Coastguard Worker run();
208*8975f5c5SAndroid Build Coastguard Worker }
209*8975f5c5SAndroid Build Coastguard Worker
210*8975f5c5SAndroid Build Coastguard Worker using namespace angle;
211*8975f5c5SAndroid Build Coastguard Worker using namespace params;
212*8975f5c5SAndroid Build Coastguard Worker using P = DrawElementsPerfParams;
213*8975f5c5SAndroid Build Coastguard Worker
CombineIndexType(const P & in,GLenum indexType)214*8975f5c5SAndroid Build Coastguard Worker P CombineIndexType(const P &in, GLenum indexType)
215*8975f5c5SAndroid Build Coastguard Worker {
216*8975f5c5SAndroid Build Coastguard Worker P out = in;
217*8975f5c5SAndroid Build Coastguard Worker out.type = indexType;
218*8975f5c5SAndroid Build Coastguard Worker return out;
219*8975f5c5SAndroid Build Coastguard Worker }
220*8975f5c5SAndroid Build Coastguard Worker
CombineIndexBufferChanged(const P & in,bool indexBufferChanged)221*8975f5c5SAndroid Build Coastguard Worker P CombineIndexBufferChanged(const P &in, bool indexBufferChanged)
222*8975f5c5SAndroid Build Coastguard Worker {
223*8975f5c5SAndroid Build Coastguard Worker P out = in;
224*8975f5c5SAndroid Build Coastguard Worker out.indexBufferChanged = indexBufferChanged;
225*8975f5c5SAndroid Build Coastguard Worker
226*8975f5c5SAndroid Build Coastguard Worker // Scale down iterations for slower tests.
227*8975f5c5SAndroid Build Coastguard Worker if (indexBufferChanged)
228*8975f5c5SAndroid Build Coastguard Worker out.iterationsPerStep /= 100;
229*8975f5c5SAndroid Build Coastguard Worker
230*8975f5c5SAndroid Build Coastguard Worker return out;
231*8975f5c5SAndroid Build Coastguard Worker }
232*8975f5c5SAndroid Build Coastguard Worker
233*8975f5c5SAndroid Build Coastguard Worker std::vector<GLenum> gIndexTypes = {GL_UNSIGNED_INT, GL_UNSIGNED_SHORT};
234*8975f5c5SAndroid Build Coastguard Worker std::vector<P> gWithIndexType = CombineWithValues({P()}, gIndexTypes, CombineIndexType);
235*8975f5c5SAndroid Build Coastguard Worker std::vector<P> gWithRenderer =
236*8975f5c5SAndroid Build Coastguard Worker CombineWithFuncs(gWithIndexType, {D3D11<P>, GL<P>, Metal<P>, Vulkan<P>, WGL<P>});
237*8975f5c5SAndroid Build Coastguard Worker std::vector<P> gWithChange =
238*8975f5c5SAndroid Build Coastguard Worker CombineWithValues(gWithRenderer, {false, true}, CombineIndexBufferChanged);
239*8975f5c5SAndroid Build Coastguard Worker std::vector<P> gWithDevice = CombineWithFuncs(gWithChange, {Passthrough<P>, NullDevice<P>});
240*8975f5c5SAndroid Build Coastguard Worker
241*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ARRAY(DrawElementsPerfBenchmark, gWithDevice);
242*8975f5c5SAndroid Build Coastguard Worker
243*8975f5c5SAndroid Build Coastguard Worker } // anonymous namespace
244