1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2014 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 // InterleavedAttributeData:
7*8975f5c5SAndroid Build Coastguard Worker // Performance test for draws using interleaved attribute data in vertex buffers.
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 "util/shader_utils.h"
14*8975f5c5SAndroid Build Coastguard Worker
15*8975f5c5SAndroid Build Coastguard Worker using namespace angle;
16*8975f5c5SAndroid Build Coastguard Worker
17*8975f5c5SAndroid Build Coastguard Worker namespace
18*8975f5c5SAndroid Build Coastguard Worker {
19*8975f5c5SAndroid Build Coastguard Worker
20*8975f5c5SAndroid Build Coastguard Worker struct InterleavedAttributeDataParams final : public RenderTestParams
21*8975f5c5SAndroid Build Coastguard Worker {
InterleavedAttributeDataParams__anon69ff6b160111::InterleavedAttributeDataParams22*8975f5c5SAndroid Build Coastguard Worker InterleavedAttributeDataParams()
23*8975f5c5SAndroid Build Coastguard Worker {
24*8975f5c5SAndroid Build Coastguard Worker iterationsPerStep = 1;
25*8975f5c5SAndroid Build Coastguard Worker
26*8975f5c5SAndroid Build Coastguard Worker // Common default values
27*8975f5c5SAndroid Build Coastguard Worker majorVersion = 2;
28*8975f5c5SAndroid Build Coastguard Worker minorVersion = 0;
29*8975f5c5SAndroid Build Coastguard Worker windowWidth = 512;
30*8975f5c5SAndroid Build Coastguard Worker windowHeight = 512;
31*8975f5c5SAndroid Build Coastguard Worker numSprites = 3000;
32*8975f5c5SAndroid Build Coastguard Worker }
33*8975f5c5SAndroid Build Coastguard Worker
34*8975f5c5SAndroid Build Coastguard Worker // static parameters
35*8975f5c5SAndroid Build Coastguard Worker unsigned int numSprites;
36*8975f5c5SAndroid Build Coastguard Worker };
37*8975f5c5SAndroid Build Coastguard Worker
operator <<(std::ostream & os,const InterleavedAttributeDataParams & params)38*8975f5c5SAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &os, const InterleavedAttributeDataParams ¶ms)
39*8975f5c5SAndroid Build Coastguard Worker {
40*8975f5c5SAndroid Build Coastguard Worker os << params.backendAndStory().substr(1);
41*8975f5c5SAndroid Build Coastguard Worker
42*8975f5c5SAndroid Build Coastguard Worker if (params.eglParameters.majorVersion != EGL_DONT_CARE)
43*8975f5c5SAndroid Build Coastguard Worker {
44*8975f5c5SAndroid Build Coastguard Worker os << "_" << params.eglParameters.majorVersion << "_" << params.eglParameters.minorVersion;
45*8975f5c5SAndroid Build Coastguard Worker }
46*8975f5c5SAndroid Build Coastguard Worker
47*8975f5c5SAndroid Build Coastguard Worker return os;
48*8975f5c5SAndroid Build Coastguard Worker }
49*8975f5c5SAndroid Build Coastguard Worker
50*8975f5c5SAndroid Build Coastguard Worker class InterleavedAttributeDataBenchmark
51*8975f5c5SAndroid Build Coastguard Worker : public ANGLERenderTest,
52*8975f5c5SAndroid Build Coastguard Worker public ::testing::WithParamInterface<InterleavedAttributeDataParams>
53*8975f5c5SAndroid Build Coastguard Worker {
54*8975f5c5SAndroid Build Coastguard Worker public:
55*8975f5c5SAndroid Build Coastguard Worker InterleavedAttributeDataBenchmark();
56*8975f5c5SAndroid Build Coastguard Worker
57*8975f5c5SAndroid Build Coastguard Worker void initializeBenchmark() override;
58*8975f5c5SAndroid Build Coastguard Worker void destroyBenchmark() override;
59*8975f5c5SAndroid Build Coastguard Worker void drawBenchmark() override;
60*8975f5c5SAndroid Build Coastguard Worker
61*8975f5c5SAndroid Build Coastguard Worker private:
62*8975f5c5SAndroid Build Coastguard Worker GLuint mPointSpriteProgram;
63*8975f5c5SAndroid Build Coastguard Worker GLuint mPositionColorBuffer[2];
64*8975f5c5SAndroid Build Coastguard Worker
65*8975f5c5SAndroid Build Coastguard Worker // The buffers contain two floats and 3 unsigned bytes per point sprite
66*8975f5c5SAndroid Build Coastguard Worker // Has to be aligned for float access on arm
67*8975f5c5SAndroid Build Coastguard Worker const size_t mBytesPerSpriteUnaligned = 2 * sizeof(float) + 3;
68*8975f5c5SAndroid Build Coastguard Worker const size_t mBytesPerSprite =
69*8975f5c5SAndroid Build Coastguard Worker ((mBytesPerSpriteUnaligned + sizeof(float) - 1) / sizeof(float)) * sizeof(float);
70*8975f5c5SAndroid Build Coastguard Worker };
71*8975f5c5SAndroid Build Coastguard Worker
InterleavedAttributeDataBenchmark()72*8975f5c5SAndroid Build Coastguard Worker InterleavedAttributeDataBenchmark::InterleavedAttributeDataBenchmark()
73*8975f5c5SAndroid Build Coastguard Worker : ANGLERenderTest("InterleavedAttributeData", GetParam()), mPointSpriteProgram(0)
74*8975f5c5SAndroid Build Coastguard Worker {
75*8975f5c5SAndroid Build Coastguard Worker if (GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
76*8975f5c5SAndroid Build Coastguard Worker {
77*8975f5c5SAndroid Build Coastguard Worker skipTest("http://crbug.com/921004 Timing out on Intel");
78*8975f5c5SAndroid Build Coastguard Worker }
79*8975f5c5SAndroid Build Coastguard Worker }
80*8975f5c5SAndroid Build Coastguard Worker
initializeBenchmark()81*8975f5c5SAndroid Build Coastguard Worker void InterleavedAttributeDataBenchmark::initializeBenchmark()
82*8975f5c5SAndroid Build Coastguard Worker {
83*8975f5c5SAndroid Build Coastguard Worker const auto ¶ms = GetParam();
84*8975f5c5SAndroid Build Coastguard Worker
85*8975f5c5SAndroid Build Coastguard Worker // Compile point sprite shaders
86*8975f5c5SAndroid Build Coastguard Worker constexpr char kVS[] =
87*8975f5c5SAndroid Build Coastguard Worker "attribute vec4 aPosition;"
88*8975f5c5SAndroid Build Coastguard Worker "attribute vec4 aColor;"
89*8975f5c5SAndroid Build Coastguard Worker "varying vec4 vColor;"
90*8975f5c5SAndroid Build Coastguard Worker "void main()"
91*8975f5c5SAndroid Build Coastguard Worker "{"
92*8975f5c5SAndroid Build Coastguard Worker " gl_PointSize = 25.0;"
93*8975f5c5SAndroid Build Coastguard Worker " gl_Position = aPosition;"
94*8975f5c5SAndroid Build Coastguard Worker " vColor = aColor;"
95*8975f5c5SAndroid Build Coastguard Worker "}";
96*8975f5c5SAndroid Build Coastguard Worker
97*8975f5c5SAndroid Build Coastguard Worker constexpr char kFS[] =
98*8975f5c5SAndroid Build Coastguard Worker "precision mediump float;"
99*8975f5c5SAndroid Build Coastguard Worker "varying vec4 vColor;"
100*8975f5c5SAndroid Build Coastguard Worker "void main()"
101*8975f5c5SAndroid Build Coastguard Worker "{"
102*8975f5c5SAndroid Build Coastguard Worker " gl_FragColor = vColor;"
103*8975f5c5SAndroid Build Coastguard Worker "}";
104*8975f5c5SAndroid Build Coastguard Worker
105*8975f5c5SAndroid Build Coastguard Worker mPointSpriteProgram = CompileProgram(kVS, kFS);
106*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(0u, mPointSpriteProgram);
107*8975f5c5SAndroid Build Coastguard Worker
108*8975f5c5SAndroid Build Coastguard Worker glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
109*8975f5c5SAndroid Build Coastguard Worker
110*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < ArraySize(mPositionColorBuffer); i++)
111*8975f5c5SAndroid Build Coastguard Worker {
112*8975f5c5SAndroid Build Coastguard Worker // Set up initial data for pointsprite positions and colors
113*8975f5c5SAndroid Build Coastguard Worker std::vector<uint8_t> positionColorData(mBytesPerSprite * params.numSprites);
114*8975f5c5SAndroid Build Coastguard Worker for (unsigned int j = 0; j < params.numSprites; j++)
115*8975f5c5SAndroid Build Coastguard Worker {
116*8975f5c5SAndroid Build Coastguard Worker float pointSpriteX =
117*8975f5c5SAndroid Build Coastguard Worker (static_cast<float>(rand() % getWindow()->getWidth()) / getWindow()->getWidth()) *
118*8975f5c5SAndroid Build Coastguard Worker 2.0f -
119*8975f5c5SAndroid Build Coastguard Worker 1.0f;
120*8975f5c5SAndroid Build Coastguard Worker float pointSpriteY =
121*8975f5c5SAndroid Build Coastguard Worker (static_cast<float>(rand() % getWindow()->getHeight()) / getWindow()->getHeight()) *
122*8975f5c5SAndroid Build Coastguard Worker 2.0f -
123*8975f5c5SAndroid Build Coastguard Worker 1.0f;
124*8975f5c5SAndroid Build Coastguard Worker GLubyte pointSpriteRed = static_cast<GLubyte>(rand() % 255);
125*8975f5c5SAndroid Build Coastguard Worker GLubyte pointSpriteGreen = static_cast<GLubyte>(rand() % 255);
126*8975f5c5SAndroid Build Coastguard Worker GLubyte pointSpriteBlue = static_cast<GLubyte>(rand() % 255);
127*8975f5c5SAndroid Build Coastguard Worker
128*8975f5c5SAndroid Build Coastguard Worker // Add position data for the pointsprite
129*8975f5c5SAndroid Build Coastguard Worker *reinterpret_cast<float *>(
130*8975f5c5SAndroid Build Coastguard Worker &(positionColorData[j * mBytesPerSprite + 0 * sizeof(float) + 0])) =
131*8975f5c5SAndroid Build Coastguard Worker pointSpriteX; // X
132*8975f5c5SAndroid Build Coastguard Worker *reinterpret_cast<float *>(
133*8975f5c5SAndroid Build Coastguard Worker &(positionColorData[j * mBytesPerSprite + 1 * sizeof(float) + 0])) =
134*8975f5c5SAndroid Build Coastguard Worker pointSpriteY; // Y
135*8975f5c5SAndroid Build Coastguard Worker
136*8975f5c5SAndroid Build Coastguard Worker // Add color data for the pointsprite
137*8975f5c5SAndroid Build Coastguard Worker positionColorData[j * mBytesPerSprite + 2 * sizeof(float) + 0] = pointSpriteRed; // R
138*8975f5c5SAndroid Build Coastguard Worker positionColorData[j * mBytesPerSprite + 2 * sizeof(float) + 1] = pointSpriteGreen; // G
139*8975f5c5SAndroid Build Coastguard Worker positionColorData[j * mBytesPerSprite + 2 * sizeof(float) + 2] = pointSpriteBlue; // B
140*8975f5c5SAndroid Build Coastguard Worker }
141*8975f5c5SAndroid Build Coastguard Worker
142*8975f5c5SAndroid Build Coastguard Worker // Generate the GL buffer with the position/color data
143*8975f5c5SAndroid Build Coastguard Worker glGenBuffers(1, &mPositionColorBuffer[i]);
144*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mPositionColorBuffer[i]);
145*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, params.numSprites * mBytesPerSprite, &(positionColorData[0]),
146*8975f5c5SAndroid Build Coastguard Worker GL_STATIC_DRAW);
147*8975f5c5SAndroid Build Coastguard Worker }
148*8975f5c5SAndroid Build Coastguard Worker
149*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
150*8975f5c5SAndroid Build Coastguard Worker }
151*8975f5c5SAndroid Build Coastguard Worker
destroyBenchmark()152*8975f5c5SAndroid Build Coastguard Worker void InterleavedAttributeDataBenchmark::destroyBenchmark()
153*8975f5c5SAndroid Build Coastguard Worker {
154*8975f5c5SAndroid Build Coastguard Worker glDeleteProgram(mPointSpriteProgram);
155*8975f5c5SAndroid Build Coastguard Worker
156*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < ArraySize(mPositionColorBuffer); i++)
157*8975f5c5SAndroid Build Coastguard Worker {
158*8975f5c5SAndroid Build Coastguard Worker glDeleteBuffers(1, &mPositionColorBuffer[i]);
159*8975f5c5SAndroid Build Coastguard Worker }
160*8975f5c5SAndroid Build Coastguard Worker }
161*8975f5c5SAndroid Build Coastguard Worker
drawBenchmark()162*8975f5c5SAndroid Build Coastguard Worker void InterleavedAttributeDataBenchmark::drawBenchmark()
163*8975f5c5SAndroid Build Coastguard Worker {
164*8975f5c5SAndroid Build Coastguard Worker glClear(GL_COLOR_BUFFER_BIT);
165*8975f5c5SAndroid Build Coastguard Worker
166*8975f5c5SAndroid Build Coastguard Worker for (size_t k = 0; k < 20; k++)
167*8975f5c5SAndroid Build Coastguard Worker {
168*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < ArraySize(mPositionColorBuffer); i++)
169*8975f5c5SAndroid Build Coastguard Worker {
170*8975f5c5SAndroid Build Coastguard Worker // Firstly get the attribute locations for the program
171*8975f5c5SAndroid Build Coastguard Worker glUseProgram(mPointSpriteProgram);
172*8975f5c5SAndroid Build Coastguard Worker GLint positionLocation = glGetAttribLocation(mPointSpriteProgram, "aPosition");
173*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(positionLocation, -1);
174*8975f5c5SAndroid Build Coastguard Worker GLint colorLocation = glGetAttribLocation(mPointSpriteProgram, "aColor");
175*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(colorLocation, -1);
176*8975f5c5SAndroid Build Coastguard Worker
177*8975f5c5SAndroid Build Coastguard Worker // Bind the position data from one buffer
178*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mPositionColorBuffer[i]);
179*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(positionLocation);
180*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE,
181*8975f5c5SAndroid Build Coastguard Worker static_cast<GLsizei>(mBytesPerSprite), 0);
182*8975f5c5SAndroid Build Coastguard Worker
183*8975f5c5SAndroid Build Coastguard Worker // But bind the color data from the other buffer.
184*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER,
185*8975f5c5SAndroid Build Coastguard Worker mPositionColorBuffer[(i + 1) % ArraySize(mPositionColorBuffer)]);
186*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(colorLocation);
187*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(colorLocation, 3, GL_UNSIGNED_BYTE, GL_TRUE,
188*8975f5c5SAndroid Build Coastguard Worker static_cast<GLsizei>(mBytesPerSprite),
189*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<void *>(2 * sizeof(float)));
190*8975f5c5SAndroid Build Coastguard Worker
191*8975f5c5SAndroid Build Coastguard Worker // Then draw the colored pointsprites
192*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_POINTS, 0, GetParam().numSprites);
193*8975f5c5SAndroid Build Coastguard Worker
194*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(positionLocation);
195*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(colorLocation);
196*8975f5c5SAndroid Build Coastguard Worker }
197*8975f5c5SAndroid Build Coastguard Worker }
198*8975f5c5SAndroid Build Coastguard Worker
199*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
200*8975f5c5SAndroid Build Coastguard Worker }
201*8975f5c5SAndroid Build Coastguard Worker
TEST_P(InterleavedAttributeDataBenchmark,Run)202*8975f5c5SAndroid Build Coastguard Worker TEST_P(InterleavedAttributeDataBenchmark, Run)
203*8975f5c5SAndroid Build Coastguard Worker {
204*8975f5c5SAndroid Build Coastguard Worker run();
205*8975f5c5SAndroid Build Coastguard Worker }
206*8975f5c5SAndroid Build Coastguard Worker
D3D11Params()207*8975f5c5SAndroid Build Coastguard Worker InterleavedAttributeDataParams D3D11Params()
208*8975f5c5SAndroid Build Coastguard Worker {
209*8975f5c5SAndroid Build Coastguard Worker InterleavedAttributeDataParams params;
210*8975f5c5SAndroid Build Coastguard Worker params.eglParameters = egl_platform::D3D11();
211*8975f5c5SAndroid Build Coastguard Worker return params;
212*8975f5c5SAndroid Build Coastguard Worker }
213*8975f5c5SAndroid Build Coastguard Worker
MetalParams()214*8975f5c5SAndroid Build Coastguard Worker InterleavedAttributeDataParams MetalParams()
215*8975f5c5SAndroid Build Coastguard Worker {
216*8975f5c5SAndroid Build Coastguard Worker InterleavedAttributeDataParams params;
217*8975f5c5SAndroid Build Coastguard Worker params.eglParameters = egl_platform::METAL();
218*8975f5c5SAndroid Build Coastguard Worker return params;
219*8975f5c5SAndroid Build Coastguard Worker }
220*8975f5c5SAndroid Build Coastguard Worker
OpenGLOrGLESParams()221*8975f5c5SAndroid Build Coastguard Worker InterleavedAttributeDataParams OpenGLOrGLESParams()
222*8975f5c5SAndroid Build Coastguard Worker {
223*8975f5c5SAndroid Build Coastguard Worker InterleavedAttributeDataParams params;
224*8975f5c5SAndroid Build Coastguard Worker params.eglParameters = egl_platform::OPENGL_OR_GLES();
225*8975f5c5SAndroid Build Coastguard Worker return params;
226*8975f5c5SAndroid Build Coastguard Worker }
227*8975f5c5SAndroid Build Coastguard Worker
VulkanParams()228*8975f5c5SAndroid Build Coastguard Worker InterleavedAttributeDataParams VulkanParams()
229*8975f5c5SAndroid Build Coastguard Worker {
230*8975f5c5SAndroid Build Coastguard Worker InterleavedAttributeDataParams params;
231*8975f5c5SAndroid Build Coastguard Worker params.eglParameters = egl_platform::VULKAN();
232*8975f5c5SAndroid Build Coastguard Worker return params;
233*8975f5c5SAndroid Build Coastguard Worker }
234*8975f5c5SAndroid Build Coastguard Worker
235*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST(InterleavedAttributeDataBenchmark,
236*8975f5c5SAndroid Build Coastguard Worker D3D11Params(),
237*8975f5c5SAndroid Build Coastguard Worker MetalParams(),
238*8975f5c5SAndroid Build Coastguard Worker OpenGLOrGLESParams(),
239*8975f5c5SAndroid Build Coastguard Worker VulkanParams());
240*8975f5c5SAndroid Build Coastguard Worker
241*8975f5c5SAndroid Build Coastguard Worker } // anonymous namespace
242