blob: f55fb6545fbd1d896303a5bf862a2eb18e36e703 [file] [log] [blame]
joshualittf06c3892015-07-01 06:20:13 -07001/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "Benchmark.h"
9#include "SkCanvas.h"
10#include "SkImageEncoder.h"
joshualitt74a07db2015-07-01 12:39:07 -070011
joshualittf06c3892015-07-01 06:20:13 -070012#if SK_SUPPORT_GPU
joshualitt74a07db2015-07-01 12:39:07 -070013#include "GLBench.h"
joshualittf06c3892015-07-01 06:20:13 -070014#include "gl/GrGLGLSL.h"
15#include "gl/GrGLInterface.h"
16#include "gl/GrGLShaderVar.h"
17#include "gl/GrGLUtil.h"
18#include "glsl/GrGLSLCaps.h"
19#include <stdio.h>
20
21/*
22 * This is a native GL benchmark for determining the cost of uploading vertex attributes
23 */
joshualitt74a07db2015-07-01 12:39:07 -070024class GLVertexAttributesBench : public GLBench {
joshualittf06c3892015-07-01 06:20:13 -070025public:
26 GLVertexAttributesBench(uint32_t attribs)
27 : fTexture(0)
28 , fBuffers(0)
29 , fProgram(0)
joshualittf06c3892015-07-01 06:20:13 -070030 , fVBO(0)
31 , fAttribs(attribs)
32 , fStride(2 * sizeof(SkPoint) + fAttribs * sizeof(GrGLfloat) * 4) {
33 fName.appendf("GLVertexAttributesBench_%d", fAttribs);
34 }
35
36protected:
37 const char* onGetName() override { return fName.c_str(); }
joshualitt74a07db2015-07-01 12:39:07 -070038 void setup(const GrGLContext*) override;
39 void glDraw(const int loops, const GrGLContext*) override;
40 void teardown(const GrGLInterface*) override;
joshualittf06c3892015-07-01 06:20:13 -070041
42 static const GrGLuint kScreenWidth = 800;
43 static const GrGLuint kScreenHeight = 600;
44 static const uint32_t kNumTri = 10000;
45 static const uint32_t kVerticesPerTri = 3;
46 static const uint32_t kDrawMultiplier = 512;
47 static const uint32_t kMaxAttribs = 7;
48
49private:
joshualitt74a07db2015-07-01 12:39:07 -070050 GrGLuint setupShader(const GrGLContext*, uint32_t attribs, uint32_t maxAttribs);
51
joshualittf06c3892015-07-01 06:20:13 -070052 GrGLuint fTexture;
53 SkTArray<GrGLuint> fBuffers;
54 GrGLuint fProgram;
joshualittf06c3892015-07-01 06:20:13 -070055 GrGLuint fVBO;
56 SkTArray<unsigned char> fVertices;
57 uint32_t fAttribs;
58 size_t fStride;
59 SkString fName;
60 typedef Benchmark INHERITED;
61};
62
joshualittf06c3892015-07-01 06:20:13 -070063///////////////////////////////////////////////////////////////////////////////////////////////////
64
joshualitt74a07db2015-07-01 12:39:07 -070065GrGLuint GLVertexAttributesBench::setupShader(const GrGLContext* ctx, uint32_t attribs,
66 uint32_t maxAttribs) {
joshualittf06c3892015-07-01 06:20:13 -070067 const char* version = GrGLGetGLSLVersionDecl(*ctx);
68
69 // setup vertex shader
70 GrGLShaderVar aPosition("a_position", kVec4f_GrSLType, GrShaderVar::kAttribute_TypeModifier);
71 SkTArray<GrGLShaderVar> aVars;
72 SkTArray<GrGLShaderVar> oVars;
73
74 SkString vshaderTxt(version);
75 aPosition.appendDecl(*ctx, &vshaderTxt);
76 vshaderTxt.append(";\n");
77
78 for (uint32_t i = 0; i < attribs; i++) {
79 SkString aname;
80 aname.appendf("a_color_%d", i);
81 aVars.push_back(GrGLShaderVar(aname.c_str(),
82 kVec4f_GrSLType,
83 GrShaderVar::kAttribute_TypeModifier));
84 aVars.back().appendDecl(*ctx, &vshaderTxt);
85 vshaderTxt.append(";\n");
86
87 }
88
89 for (uint32_t i = 0; i < maxAttribs; i++) {
90 SkString oname;
91 oname.appendf("o_color_%d", i);
92 oVars.push_back(GrGLShaderVar(oname.c_str(),
93 kVec4f_GrSLType,
94 GrShaderVar::kVaryingOut_TypeModifier));
95 oVars.back().appendDecl(*ctx, &vshaderTxt);
96 vshaderTxt.append(";\n");
97 }
98
99 vshaderTxt.append(
100 "void main()\n"
101 "{\n"
102 "gl_Position = a_position;\n");
103
104 for (uint32_t i = 0; i < attribs; i++) {
105 vshaderTxt.appendf("%s = %s;\n", oVars[i].c_str(), aVars[i].c_str());
106 }
107
108 // Passthrough position as a dummy
109 for (uint32_t i = attribs; i < maxAttribs; i++) {
joshualittbd929d92015-07-01 08:34:50 -0700110 vshaderTxt.appendf("%s = vec4(0, 0, 0, 1);\n", oVars[i].c_str());
joshualittf06c3892015-07-01 06:20:13 -0700111 }
112
113 vshaderTxt.append("}\n");
114
115 const GrGLInterface* gl = ctx->interface();
joshualittf06c3892015-07-01 06:20:13 -0700116
117 // setup fragment shader
118 GrGLShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_TypeModifier);
119 SkString fshaderTxt(version);
120 GrGLAppendGLSLDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, gl->fStandard,
121 &fshaderTxt);
122
123 const char* fsOutName;
124 if (ctx->caps()->glslCaps()->mustDeclareFragmentShaderOutput()) {
125 oFragColor.appendDecl(*ctx, &fshaderTxt);
126 fshaderTxt.append(";\n");
127 fsOutName = oFragColor.c_str();
128 } else {
129 fsOutName = "gl_FragColor";
130 }
131
132 for (uint32_t i = 0; i < maxAttribs; i++) {
133 oVars[i].setTypeModifier(GrShaderVar::kVaryingIn_TypeModifier);
134 oVars[i].appendDecl(*ctx, &fshaderTxt);
135 fshaderTxt.append(";\n");
136 }
137
138 fshaderTxt.appendf(
139 "void main()\n"
140 "{\n"
141 "%s = ", fsOutName);
142
143 fshaderTxt.appendf("%s", oVars[0].c_str());
144 for (uint32_t i = 1; i < maxAttribs; i++) {
145 fshaderTxt.appendf(" + %s", oVars[i].c_str());
146 }
147
148 fshaderTxt.append(";\n"
149 "}\n");
150
joshualitt74a07db2015-07-01 12:39:07 -0700151 return CreateProgram(gl, vshaderTxt.c_str(), fshaderTxt.c_str());
joshualittf06c3892015-07-01 06:20:13 -0700152}
153
154///////////////////////////////////////////////////////////////////////////////////////////////////
155
156void GLVertexAttributesBench::setup(const GrGLContext* ctx) {
157 const GrGLInterface* gl = ctx->interface();
joshualitt74a07db2015-07-01 12:39:07 -0700158 fTexture = SetupFramebuffer(gl, kScreenWidth, kScreenHeight);
joshualittf06c3892015-07-01 06:20:13 -0700159
joshualitt74a07db2015-07-01 12:39:07 -0700160 fProgram = setupShader(ctx, fAttribs, kMaxAttribs);
joshualittf06c3892015-07-01 06:20:13 -0700161
162 // setup matrices
163 SkMatrix viewMatrices[kNumTri];
164 for (uint32_t i = 0 ; i < kNumTri; i++) {
165 SkMatrix m = SkMatrix::I();
166 m.setScale(0.0001f, 0.0001f);
167 viewMatrices[i] = m;
168 }
169
joshualittf06c3892015-07-01 06:20:13 -0700170 // presetup vertex attributes, color is set to be a light gray no matter how many vertex
171 // attributes are used
172 float targetColor = 0.9f;
173 float colorContribution = targetColor / fAttribs;
174 fVertices.reset(static_cast<int>(kVerticesPerTri * kNumTri * fStride));
175 for (uint32_t i = 0; i < kNumTri; i++) {
176 unsigned char* ptr = &fVertices[static_cast<int>(i * kVerticesPerTri * fStride)];
177 SkPoint* p = reinterpret_cast<SkPoint*>(ptr);
178 p->set(-1.0f, -1.0f); p++; p->set( 0.0f, 1.0f);
179 p = reinterpret_cast<SkPoint*>(ptr + fStride);
180 p->set( 1.0f, -1.0f); p++; p->set( 0.0f, 1.0f);
181 p = reinterpret_cast<SkPoint*>(ptr + fStride * 2);
182 p->set( 1.0f, 1.0f); p++; p->set( 0.0f, 1.0f);
183
184 SkPoint* position = reinterpret_cast<SkPoint*>(ptr);
185 viewMatrices[i].mapPointsWithStride(position, fStride, kVerticesPerTri);
186
187 // set colors
188 for (uint32_t j = 0; j < kVerticesPerTri; j++) {
189 GrGLfloat* f = reinterpret_cast<GrGLfloat*>(ptr + 2 * sizeof(SkPoint) + fStride * j);
190 for (uint32_t k = 0; k < fAttribs * 4; k += 4) {
191 f[k] = colorContribution;
192 f[k + 1] = colorContribution;
193 f[k + 2] = colorContribution;
194 f[k + 3] = 1.0f;
195 }
196 }
197 }
198
199 GR_GL_CALL(gl, GenBuffers(1, &fVBO));
200 fBuffers.push_back(fVBO);
201
202 // clear screen
203 GR_GL_CALL(gl, ClearColor(0.03f, 0.03f, 0.03f, 1.0f));
204 GR_GL_CALL(gl, Clear(GR_GL_COLOR_BUFFER_BIT));
205
206 // set us up to draw
207 GR_GL_CALL(gl, UseProgram(fProgram));
joshualittf06c3892015-07-01 06:20:13 -0700208}
209
joshualitt74a07db2015-07-01 12:39:07 -0700210void GLVertexAttributesBench::glDraw(const int loops, const GrGLContext* ctx) {
joshualittf06c3892015-07-01 06:20:13 -0700211 const GrGLInterface* gl = ctx->interface();
212
213 // upload vertex attributes
214 GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, fVBO));
215 GR_GL_CALL(gl, EnableVertexAttribArray(0));
216 GR_GL_CALL(gl, VertexAttribPointer(0, 4, GR_GL_FLOAT, GR_GL_FALSE, (GrGLsizei)fStride,
217 (GrGLvoid*)0));
218
219 size_t runningStride = 2 * sizeof(SkPoint);
220 for (uint32_t i = 0; i < fAttribs; i++) {
221 int attribId = i + 1;
222 GR_GL_CALL(gl, EnableVertexAttribArray(attribId));
223 GR_GL_CALL(gl, VertexAttribPointer(attribId, 4, GR_GL_FLOAT, GR_GL_FALSE,
224 (GrGLsizei)fStride, (GrGLvoid*)(runningStride)));
225 runningStride += sizeof(GrGLfloat) * 4;
226 }
227
228 GR_GL_CALL(gl, BufferData(GR_GL_ARRAY_BUFFER, fVertices.count(), fVertices.begin(),
229 GR_GL_STREAM_DRAW));
230
231 uint32_t maxTrianglesPerFlush = kNumTri;
232 uint32_t trianglesToDraw = loops * kDrawMultiplier;
233
234 while (trianglesToDraw > 0) {
235 uint32_t triangles = SkTMin(trianglesToDraw, maxTrianglesPerFlush);
236 GR_GL_CALL(gl, DrawArrays(GR_GL_TRIANGLES, 0, kVerticesPerTri * triangles));
237 trianglesToDraw -= triangles;
238 }
239
joshualitt74a07db2015-07-01 12:39:07 -0700240#if 0
joshualittf06c3892015-07-01 06:20:13 -0700241 //const char* filename = "/data/local/tmp/out.png";
242 SkString filename("out");
243 filename.appendf("_%s.png", this->getName());
joshualitt74a07db2015-07-01 12:39:07 -0700244 DumpImage(gl, kScreenWidth, kScreenHeight, filename.c_str());
joshualittf06c3892015-07-01 06:20:13 -0700245#endif
246}
247
joshualitt74a07db2015-07-01 12:39:07 -0700248void GLVertexAttributesBench::teardown(const GrGLInterface* gl) {
249 // teardown
250 GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, 0));
251 GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, 0));
252 GR_GL_CALL(gl, BindFramebuffer(GR_GL_FRAMEBUFFER, 0));
253 GR_GL_CALL(gl, DeleteTextures(1, &fTexture));
254 GR_GL_CALL(gl, DeleteProgram(fProgram));
255 GR_GL_CALL(gl, DeleteBuffers(fBuffers.count(), fBuffers.begin()));
joshualitt31b21f62015-07-16 13:40:51 -0700256 fBuffers.reset();
joshualitt74a07db2015-07-01 12:39:07 -0700257}
joshualittf06c3892015-07-01 06:20:13 -0700258
259///////////////////////////////////////////////////////////////////////////////
260
261DEF_BENCH( return new GLVertexAttributesBench(0) )
262DEF_BENCH( return new GLVertexAttributesBench(1) )
263DEF_BENCH( return new GLVertexAttributesBench(2) )
264DEF_BENCH( return new GLVertexAttributesBench(3) )
265DEF_BENCH( return new GLVertexAttributesBench(4) )
266DEF_BENCH( return new GLVertexAttributesBench(5) )
267DEF_BENCH( return new GLVertexAttributesBench(6) )
268DEF_BENCH( return new GLVertexAttributesBench(7) )
269#endif