xref: /aosp_15_r20/external/angle/src/tests/perf_tests/DrawElementsPerf.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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 &params)
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 &params = 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 &params = 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