• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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"
11 
12 #if SK_SUPPORT_GPU
13 #include "GLBench.h"
14 #include "gl/GrGLContext.h"
15 #include "gl/GrGLInterface.h"
16 #include "gl/GrGLUtil.h"
17 #include "glsl/GrGLSL.h"
18 #include "glsl/GrGLSLCaps.h"
19 #include "glsl/GrGLSLShaderVar.h"
20 #include <stdio.h>
21 
22 /*
23  * This is a native GL benchmark for determining the cost of uploading vertex attributes
24  */
25 class GLVertexAttributesBench : public GLBench {
26 public:
GLVertexAttributesBench(uint32_t attribs)27     GLVertexAttributesBench(uint32_t attribs)
28         : fTexture(0)
29         , fBuffers(0)
30         , fProgram(0)
31         , fVBO(0)
32         , fAttribs(attribs)
33         , fStride(2 * sizeof(SkPoint) + fAttribs * sizeof(GrGLfloat) * 4) {
34         fName.appendf("GLVertexAttributesBench_%d", fAttribs);
35     }
36 
37 protected:
onGetName()38     const char* onGetName() override { return fName.c_str(); }
39     void setup(const GrGLContext*) override;
40     void glDraw(int loops, const GrGLContext*) override;
41     void teardown(const GrGLInterface*) override;
42 
43     static const GrGLuint kScreenWidth = 800;
44     static const GrGLuint kScreenHeight = 600;
45     static const uint32_t kNumTri = 10000;
46     static const uint32_t kVerticesPerTri = 3;
47     static const uint32_t kDrawMultiplier = 512;
48     static const uint32_t kMaxAttribs = 7;
49 
50 private:
51     GrGLuint setupShader(const GrGLContext*, uint32_t attribs, uint32_t maxAttribs);
52 
53     GrGLuint fTexture;
54     SkTArray<GrGLuint> fBuffers;
55     GrGLuint fProgram;
56     GrGLuint fVBO;
57     SkTArray<unsigned char> fVertices;
58     uint32_t fAttribs;
59     size_t fStride;
60     SkString fName;
61     typedef Benchmark INHERITED;
62 };
63 
64 ///////////////////////////////////////////////////////////////////////////////////////////////////
65 
setupShader(const GrGLContext * ctx,uint32_t attribs,uint32_t maxAttribs)66 GrGLuint GLVertexAttributesBench::setupShader(const GrGLContext* ctx, uint32_t attribs,
67                                               uint32_t maxAttribs) {
68     const GrGLSLCaps* glslCaps = ctx->caps()->glslCaps();
69     const char* version = glslCaps->versionDeclString();
70 
71     // setup vertex shader
72     GrGLSLShaderVar aPosition("a_position", kVec4f_GrSLType, GrShaderVar::kAttribute_TypeModifier);
73     SkTArray<GrGLSLShaderVar> aVars;
74     SkTArray<GrGLSLShaderVar> oVars;
75 
76     SkString vshaderTxt(version);
77     aPosition.appendDecl(glslCaps, &vshaderTxt);
78     vshaderTxt.append(";\n");
79 
80     for (uint32_t i = 0; i < attribs; i++) {
81         SkString aname;
82         aname.appendf("a_color_%d", i);
83         aVars.push_back(GrGLSLShaderVar(aname.c_str(),
84                                       kVec4f_GrSLType,
85                                       GrShaderVar::kAttribute_TypeModifier));
86         aVars.back().appendDecl(glslCaps, &vshaderTxt);
87         vshaderTxt.append(";\n");
88 
89     }
90 
91     for (uint32_t i = 0; i < maxAttribs; i++) {
92         SkString oname;
93         oname.appendf("o_color_%d", i);
94         oVars.push_back(GrGLSLShaderVar(oname.c_str(),
95                                       kVec4f_GrSLType,
96                                       GrShaderVar::kVaryingOut_TypeModifier));
97         oVars.back().appendDecl(glslCaps, &vshaderTxt);
98         vshaderTxt.append(";\n");
99     }
100 
101     vshaderTxt.append(
102             "void main()\n"
103             "{\n"
104                 "gl_Position = a_position;\n");
105 
106     for (uint32_t i = 0; i < attribs; i++) {
107         vshaderTxt.appendf("%s = %s;\n", oVars[i].c_str(), aVars[i].c_str());
108     }
109 
110     // Passthrough position as a dummy
111     for (uint32_t i = attribs; i < maxAttribs; i++) {
112         vshaderTxt.appendf("%s = vec4(0, 0, 0, 1);\n", oVars[i].c_str());
113     }
114 
115     vshaderTxt.append("}\n");
116 
117     const GrGLInterface* gl = ctx->interface();
118 
119     // setup fragment shader
120     GrGLSLShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_TypeModifier);
121     SkString fshaderTxt(version);
122     GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, *glslCaps, &fshaderTxt);
123 
124     const char* fsOutName;
125     if (glslCaps->mustDeclareFragmentShaderOutput()) {
126         oFragColor.appendDecl(glslCaps, &fshaderTxt);
127         fshaderTxt.append(";\n");
128         fsOutName = oFragColor.c_str();
129     } else {
130         fsOutName = "gl_FragColor";
131     }
132 
133     for (uint32_t i = 0; i < maxAttribs; i++) {
134         oVars[i].setTypeModifier(GrShaderVar::kVaryingIn_TypeModifier);
135         oVars[i].appendDecl(glslCaps, &fshaderTxt);
136         fshaderTxt.append(";\n");
137     }
138 
139     fshaderTxt.appendf(
140             "void main()\n"
141             "{\n"
142                "%s = ", fsOutName);
143 
144     fshaderTxt.appendf("%s", oVars[0].c_str());
145     for (uint32_t i = 1; i < maxAttribs; i++) {
146         fshaderTxt.appendf(" + %s", oVars[i].c_str());
147     }
148 
149     fshaderTxt.append(";\n"
150                       "}\n");
151 
152     return CreateProgram(gl, vshaderTxt.c_str(), fshaderTxt.c_str());
153 }
154 
155 ///////////////////////////////////////////////////////////////////////////////////////////////////
156 
setup(const GrGLContext * ctx)157 void GLVertexAttributesBench::setup(const GrGLContext* ctx) {
158     const GrGLInterface* gl = ctx->interface();
159     fTexture = SetupFramebuffer(gl, kScreenWidth, kScreenHeight);
160 
161     fProgram = setupShader(ctx, fAttribs, kMaxAttribs);
162 
163     // setup matrices
164     SkMatrix viewMatrices[kNumTri];
165     for (uint32_t i = 0 ; i < kNumTri; i++) {
166         SkMatrix m = SkMatrix::I();
167         m.setScale(0.0001f, 0.0001f);
168         viewMatrices[i] = m;
169     }
170 
171     // presetup vertex attributes, color is set to be a light gray no matter how many vertex
172     // attributes are used
173     float targetColor = 0.9f;
174     float colorContribution = targetColor / fAttribs;
175     fVertices.reset(static_cast<int>(kVerticesPerTri * kNumTri * fStride));
176     for (uint32_t i = 0; i < kNumTri; i++) {
177         unsigned char* ptr = &fVertices[static_cast<int>(i * kVerticesPerTri * fStride)];
178         SkPoint* p = reinterpret_cast<SkPoint*>(ptr);
179         p->set(-1.0f, -1.0f); p++; p->set( 0.0f, 1.0f);
180         p = reinterpret_cast<SkPoint*>(ptr + fStride);
181         p->set( 1.0f, -1.0f); p++; p->set( 0.0f, 1.0f);
182         p = reinterpret_cast<SkPoint*>(ptr + fStride * 2);
183         p->set( 1.0f,  1.0f); p++; p->set( 0.0f, 1.0f);
184 
185         SkPoint* position = reinterpret_cast<SkPoint*>(ptr);
186         viewMatrices[i].mapPointsWithStride(position, fStride, kVerticesPerTri);
187 
188         // set colors
189         for (uint32_t j = 0; j < kVerticesPerTri; j++) {
190             GrGLfloat* f = reinterpret_cast<GrGLfloat*>(ptr + 2 * sizeof(SkPoint) + fStride * j);
191             for (uint32_t k = 0; k < fAttribs * 4; k += 4) {
192                 f[k] = colorContribution;
193                 f[k + 1] = colorContribution;
194                 f[k + 2] = colorContribution;
195                 f[k + 3] = 1.0f;
196             }
197         }
198     }
199 
200     GR_GL_CALL(gl, GenBuffers(1, &fVBO));
201     fBuffers.push_back(fVBO);
202 
203     // clear screen
204     GR_GL_CALL(gl, ClearColor(0.03f, 0.03f, 0.03f, 1.0f));
205     GR_GL_CALL(gl, Clear(GR_GL_COLOR_BUFFER_BIT));
206 
207     // set us up to draw
208     GR_GL_CALL(gl, UseProgram(fProgram));
209 }
210 
glDraw(int loops,const GrGLContext * ctx)211 void GLVertexAttributesBench::glDraw(int loops, const GrGLContext* ctx) {
212     const GrGLInterface* gl = ctx->interface();
213 
214     // upload vertex attributes
215     GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, fVBO));
216     GR_GL_CALL(gl, EnableVertexAttribArray(0));
217     GR_GL_CALL(gl, VertexAttribPointer(0, 4, GR_GL_FLOAT, GR_GL_FALSE, (GrGLsizei)fStride,
218                                        (GrGLvoid*)0));
219 
220     size_t runningStride = 2 * sizeof(SkPoint);
221     for (uint32_t i = 0; i < fAttribs; i++) {
222         int attribId = i + 1;
223         GR_GL_CALL(gl, EnableVertexAttribArray(attribId));
224         GR_GL_CALL(gl, VertexAttribPointer(attribId, 4, GR_GL_FLOAT, GR_GL_FALSE,
225                                            (GrGLsizei)fStride, (GrGLvoid*)(runningStride)));
226         runningStride += sizeof(GrGLfloat) * 4;
227     }
228 
229     GR_GL_CALL(gl, BufferData(GR_GL_ARRAY_BUFFER, fVertices.count(), fVertices.begin(),
230                               GR_GL_STREAM_DRAW));
231 
232     uint32_t maxTrianglesPerFlush = kNumTri;
233     uint32_t trianglesToDraw = loops * kDrawMultiplier;
234 
235     while (trianglesToDraw > 0) {
236         uint32_t triangles = SkTMin(trianglesToDraw, maxTrianglesPerFlush);
237         GR_GL_CALL(gl, DrawArrays(GR_GL_TRIANGLES, 0, kVerticesPerTri * triangles));
238         trianglesToDraw -= triangles;
239     }
240 
241 #if 0
242     //const char* filename = "/data/local/tmp/out.png";
243     SkString filename("out");
244     filename.appendf("_%s.png", this->getName());
245     DumpImage(gl, kScreenWidth, kScreenHeight, filename.c_str());
246 #endif
247 }
248 
teardown(const GrGLInterface * gl)249 void GLVertexAttributesBench::teardown(const GrGLInterface* gl) {
250     // teardown
251     GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, 0));
252     GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, 0));
253     GR_GL_CALL(gl, BindFramebuffer(GR_GL_FRAMEBUFFER, 0));
254     GR_GL_CALL(gl, DeleteTextures(1, &fTexture));
255     GR_GL_CALL(gl, DeleteProgram(fProgram));
256     GR_GL_CALL(gl, DeleteBuffers(fBuffers.count(), fBuffers.begin()));
257     fBuffers.reset();
258 }
259 
260 ///////////////////////////////////////////////////////////////////////////////
261 
262 DEF_BENCH( return new GLVertexAttributesBench(0) )
263 DEF_BENCH( return new GLVertexAttributesBench(1) )
264 DEF_BENCH( return new GLVertexAttributesBench(2) )
265 DEF_BENCH( return new GLVertexAttributesBench(3) )
266 DEF_BENCH( return new GLVertexAttributesBench(4) )
267 DEF_BENCH( return new GLVertexAttributesBench(5) )
268 DEF_BENCH( return new GLVertexAttributesBench(6) )
269 DEF_BENCH( return new GLVertexAttributesBench(7) )
270 #endif
271