OLD | NEW |
---|---|
(Empty) | |
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" | |
tomhudson
2015/07/10 19:23:54
You don't seem to need any of these 3 includes any
wangyix
2015/07/13 17:29:52
Done.
| |
11 | |
12 #if SK_SUPPORT_GPU | |
13 #include "GLBench.h" | |
14 #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 | |
20 #include <stdio.h> | |
21 | |
22 /* | |
tomhudson
2015/07/10 19:23:54
Please make this /** so doxygen can pick it up.
Al
wangyix
2015/07/13 17:29:53
Done.
| |
23 * This is a native GL benchmark for instanced arrays vs vertex buffer objects. To benchmark this | |
24 * functionality, we draw n * kDrawMultipier triangles per run. If this number is less than | |
25 * kNumTri then we do a single draw, either with instances, or drawArrays. Othe rwise we do | |
26 * multiple draws. | |
27 * | |
28 * Additionally, there is a divisor, which if > 0 will act as a multiplier for t he number of draws | |
29 * issued. | |
30 */ | |
31 | |
32 class GLVec4ScalarBench : public GLBench { | |
33 public: | |
34 /* | |
35 * Use float or vec4 as GLSL data type for the output coverage | |
36 */ | |
37 enum CoverageSetup { | |
38 kUseScalar_CoverageSetup, | |
39 kUseVec4_CoverageSetup, | |
40 }; | |
41 | |
42 /* | |
43 * drawDiv will act as a multiplier for the number of draws we issue if > 0. ie, 2 will issue | |
44 * 2x as many draws, 4 will issue 4x as many draws etc. There is a limit ho wever, which is | |
45 * kDrawMultipier. | |
tomhudson
2015/07/10 19:23:54
Outdated comment; cut.
If the class comment is goo
wangyix
2015/07/13 17:29:52
Done.
| |
46 */ | |
47 GLVec4ScalarBench(CoverageSetup coverageSetup, uint32_t numStages) | |
48 : fCoverageSetup(coverageSetup) | |
49 , fNumStages(numStages) | |
50 , fProgram(0) | |
51 , fVAO(0) { | |
tomhudson
2015/07/10 19:23:55
Why explicitly clear fVAO but not fVBO?
wangyix
2015/07/13 17:29:53
Done.
| |
52 fName = CoverageSetupToStr(coverageSetup, numStages); | |
53 } | |
54 | |
55 protected: | |
56 const char* onGetName() override { | |
57 return fName.c_str(); | |
58 } | |
59 | |
60 const GrGLContext* onGetGLContext(const GrGLContext*) override; | |
tomhudson
2015/07/13 16:00:13
Once we've started reviewing, it's good for the re
wangyix
2015/07/13 17:29:52
Yep that was the reason. The override was specific
| |
61 void setup(const GrGLContext*) override; | |
62 void glDraw(const int loops, const GrGLContext*) override; | |
63 void teardown(const GrGLInterface*) override; | |
64 | |
65 private: | |
66 void setupSingleVbo(const GrGLInterface*, const SkMatrix*); | |
67 GrGLuint setupShader(const GrGLContext*, bool useVec4ForCoverage); | |
68 | |
69 | |
70 static SkString CoverageSetupToStr(CoverageSetup vboSetup, uint32_t numStage s) { | |
tomhudson
2015/07/10 19:23:55
Consider tweaking the function name, since you're
wangyix
2015/07/13 17:29:52
Done.
| |
71 SkString name("GLVec4ScalarBench"); | |
72 switch (vboSetup) { | |
73 default: | |
74 case kUseScalar_CoverageSetup: | |
75 name.appendf("_scalar_%u_stage", numStages); | |
76 break; | |
77 case kUseVec4_CoverageSetup: | |
78 name.appendf("_vec4_%u_stage", numStages); | |
79 break; | |
80 } | |
81 return name; | |
82 } | |
83 | |
84 static const GrGLuint kScreenWidth = 800; | |
85 static const GrGLuint kScreenHeight = 600; | |
86 static const uint32_t kNumTriPerDraw = 512; | |
87 static const uint32_t kVerticesPerTri = 3; | |
88 | |
89 SkString fName; | |
90 CoverageSetup fCoverageSetup; | |
91 uint32_t fNumStages; | |
92 GrGLuint fVBO; | |
tomhudson
2015/07/10 19:23:54
Consider writing out name instead of using abbrevi
wangyix
2015/07/13 17:29:52
Vao and Vbo are extremely common occurrences in Op
| |
93 GrGLuint fProgram; | |
94 GrGLuint fVAO; | |
tomhudson
2015/07/10 19:23:55
... particularly when two abbreviations are very c
wangyix
2015/07/13 17:29:52
Done.
| |
95 GrGLuint fTexture; | |
tomhudson
2015/07/10 19:23:55
It makes the name a bit long, but you might want t
wangyix
2015/07/13 17:29:52
Done.
| |
96 }; | |
97 | |
98 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
99 | |
100 GrGLuint GLVec4ScalarBench::setupShader(const GrGLContext* ctx, bool useVec4ForC overage) { | |
tomhudson
2015/07/10 19:23:55
Instead of passing the bool here, pass the enum! T
wangyix
2015/07/13 17:29:52
Done.
| |
101 const char* version = GrGLGetGLSLVersionDecl(*ctx); | |
102 | |
103 // setup vertex shader | |
tomhudson
2015/07/10 19:23:54
I'd like to see a "// This shader draws 4 overlapp
wangyix
2015/07/13 17:29:53
Done.
| |
104 GrGLShaderVar aPosition("a_position", kVec2f_GrSLType, GrShaderVar::kAttribu te_TypeModifier); | |
105 GrGLShaderVar oPosition("o_position", kVec2f_GrSLType, GrShaderVar::kVarying Out_TypeModifier); | |
106 GrGLShaderVar aColor("a_color", kVec3f_GrSLType, GrShaderVar::kAttribute_Typ eModifier); | |
107 GrGLShaderVar oColor("o_color", kVec3f_GrSLType, GrShaderVar::kVaryingOut_Ty peModifier); | |
108 | |
109 SkString vshaderTxt(version); | |
110 aPosition.appendDecl(*ctx, &vshaderTxt); | |
111 vshaderTxt.append(";\n"); | |
112 aColor.appendDecl(*ctx, &vshaderTxt); | |
113 vshaderTxt.append(";\n"); | |
114 oPosition.appendDecl(*ctx, &vshaderTxt); | |
115 vshaderTxt.append(";\n"); | |
116 oColor.appendDecl(*ctx, &vshaderTxt); | |
117 vshaderTxt.append(";\n"); | |
118 | |
119 vshaderTxt.append( | |
120 "void main()\n" | |
121 "{\n" | |
122 " gl_Position = vec4(a_position, 0.f, 1.f);\n" | |
123 " o_position = a_position;\n" | |
124 " o_color = a_color;\n" | |
125 "}\n"); | |
126 | |
127 const GrGLInterface* gl = ctx->interface(); | |
128 | |
129 // setup fragment shader | |
130 GrGLShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_T ypeModifier); | |
131 SkString fshaderTxt(version); | |
132 GrGLAppendGLSLDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, gl->f Standard, | |
133 &fshaderTxt); | |
134 oPosition.setTypeModifier(GrShaderVar::kVaryingIn_TypeModifier); | |
135 oPosition.appendDecl(*ctx, &fshaderTxt); | |
136 fshaderTxt.append(";\n"); | |
137 oColor.setTypeModifier(GrShaderVar::kVaryingIn_TypeModifier); | |
138 oColor.appendDecl(*ctx, &fshaderTxt); | |
139 fshaderTxt.append(";\n"); | |
140 | |
141 const char* fsOutName; | |
142 if (ctx->caps()->glslCaps()->mustDeclareFragmentShaderOutput()) { | |
143 oFragColor.appendDecl(*ctx, &fshaderTxt); | |
144 fshaderTxt.append(";\n"); | |
145 fsOutName = oFragColor.c_str(); | |
146 } else { | |
147 fsOutName = "gl_FragColor"; | |
148 } | |
149 | |
150 if (useVec4ForCoverage) { | |
151 fshaderTxt.appendf( | |
152 "void main()\n" | |
153 "{\n" | |
154 " vec4 outputColor;\n" | |
155 " vec4 outputCoverage;\n" | |
156 " outputColor = vec4(%s, 1.0);\n" | |
157 " outputCoverage = vec4(1.0);\n", | |
158 oColor.getName().c_str()); | |
159 } else { | |
160 fshaderTxt.appendf( | |
161 "void main()\n" | |
162 "{\n" | |
163 " vec4 outputColor;\n" | |
164 " float outputCoverage;\n" | |
165 " outputColor = vec4(%s, 1.0);\n" | |
166 " outputCoverage = 1.0;\n", | |
167 oColor.getName().c_str()); | |
168 } | |
169 float radius = 1.0f; | |
170 for (uint32_t i = 0; i < fNumStages; i++) { | |
tomhudson
2015/07/10 19:23:54
Why pass in fConverageSetup (or a bool derived fro
wangyix
2015/07/13 17:29:52
Done.
| |
171 float centerX = 1.0f - radius; | |
172 float centerY = 1.0f - radius; | |
173 if (useVec4ForCoverage) { | |
174 fshaderTxt.appendf( | |
175 " {\n" | |
176 " float d = length(%s - vec2(%f, %f));\n" | |
177 " float edgeAlpha = clamp(100.0 * (%f - d), 0.0, 1.0);\n" | |
178 " outputCoverage = 0.5 * outputCoverage + 0.5 * vec4(edge Alpha);\n" | |
179 " }\n", | |
180 oPosition.getName().c_str(), | |
181 centerX, centerY, | |
182 radius | |
183 ); | |
184 } else { | |
185 fshaderTxt.appendf( | |
186 " {\n" | |
187 " float d = length(%s - vec2(%f, %f));\n" | |
188 " float edgeAlpha = clamp(100.0 * (%f - d), 0.0, 1.0);\n" | |
189 " outputCoverage = 0.5 * outputCoverage + 0.5 * edgeAlpha ;\n" | |
190 " }\n", | |
191 oPosition.getName().c_str(), | |
192 centerX, centerY, | |
193 radius | |
194 ); | |
195 } | |
196 radius *= 0.8f; | |
197 } | |
198 fshaderTxt.appendf( | |
199 " {\n" | |
200 " %s = outputColor * outputCoverage;\n" | |
201 " }\n" | |
202 "}\n", | |
203 fsOutName); | |
204 | |
205 //printf("\n%s\n", fshaderTxt.c_str()); | |
tomhudson
2015/07/10 19:23:55
Remove commented-out code.
wangyix
2015/07/13 17:29:53
Done.
| |
206 | |
207 return CreateProgram(gl, vshaderTxt.c_str(), fshaderTxt.c_str()); | |
208 } | |
209 | |
210 template<typename Func> | |
211 static void setup_matrices(int numQuads, Func f) { | |
212 // We draw a really small triangle so we are not fill rate limited | |
213 for (int i = 0 ; i < numQuads; i++) { | |
214 SkMatrix m = SkMatrix::I(); | |
215 m.setScale(0.01f, 0.01f); | |
216 f(m); | |
217 } | |
218 } | |
219 | |
220 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
221 | |
222 const GrGLContext* GLVec4ScalarBench::onGetGLContext(const GrGLContext* ctx) { | |
223 // We only care about gpus with drawArraysInstanced support | |
224 if (!ctx->interface()->fFunctions.fDrawArraysInstanced) { | |
225 return NULL; | |
226 } | |
227 return ctx; | |
228 } | |
229 | |
230 struct Vertex { | |
231 SkPoint fPositions; | |
232 GrGLfloat fColors[3]; | |
233 }; | |
234 | |
235 void GLVec4ScalarBench::setupSingleVbo(const GrGLInterface* gl, | |
236 const SkMatrix* viewMatrices) { | |
tomhudson
2015/07/10 19:23:54
Nit: fix indentation
wangyix
2015/07/13 17:29:53
Done.
| |
237 // Constants for our various shader programs | |
tomhudson
2015/07/10 19:23:55
This comment is not very high-value. Omit?
wangyix
2015/07/13 17:29:52
Done.
| |
238 Vertex vertices[kVerticesPerTri * kNumTriPerDraw]; | |
239 for (uint32_t i = 0; i < kNumTriPerDraw; i++) { | |
240 Vertex* v = &vertices[i * kVerticesPerTri]; | |
241 if (i % 2 == 0) { | |
242 v[0].fPositions.set(-1.0f, -1.0f); | |
243 v[1].fPositions.set( 1.0f, -1.0f); | |
244 v[2].fPositions.set( 1.0f, 1.0f); | |
245 } else { | |
246 v[0].fPositions.set(-1.0f, -1.0f); | |
247 v[1].fPositions.set( 1.0f, 1.0f); | |
248 v[2].fPositions.set( -1.0f, 1.0f); | |
249 } | |
250 SkPoint* position = reinterpret_cast<SkPoint*>(v); | |
251 viewMatrices[i].mapPointsWithStride(position, sizeof(Vertex), kVerticesP erTri); | |
252 | |
253 // set colors | |
tomhudson
2015/07/10 19:23:55
Bad evil comment. Expurgate!
wangyix
2015/07/13 17:29:53
Done.
| |
254 GrGLfloat color[3] = {1.0f, 0.0f, 1.0f}; | |
255 for (uint32_t j = 0; j < kVerticesPerTri; j++) { | |
256 v->fColors[0] = color[0]; | |
257 v->fColors[1] = color[1]; | |
258 v->fColors[2] = color[2]; | |
259 v++; | |
260 } | |
261 } | |
262 | |
263 // setup VBO | |
tomhudson
2015/07/10 19:23:54
Low-value comment. What is it? Or why are we doing
wangyix
2015/07/13 17:29:53
Done.
| |
264 GR_GL_CALL(gl, GenBuffers(1, &fVBO)); | |
265 GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, fVBO)); | |
266 GR_GL_CALL(gl, EnableVertexAttribArray(0)); | |
267 GR_GL_CALL(gl, EnableVertexAttribArray(1)); | |
268 GR_GL_CALL(gl, VertexAttribPointer(0, 2, GR_GL_FLOAT, GR_GL_FALSE, sizeof(Ve rtex), | |
269 (GrGLvoid*)0)); | |
270 GR_GL_CALL(gl, VertexAttribPointer(1, 3, GR_GL_FLOAT, GR_GL_FALSE, sizeof(Ve rtex), | |
271 (GrGLvoid*)(sizeof(SkPoint)))); | |
272 GR_GL_CALL(gl, BufferData(GR_GL_ARRAY_BUFFER, sizeof(vertices), vertices, GR _GL_STATIC_DRAW)); | |
273 } | |
274 | |
275 void GLVec4ScalarBench::setup(const GrGLContext* ctx) { | |
276 const GrGLInterface* gl = ctx->interface(); | |
277 fTexture = SetupFramebuffer(gl, kScreenWidth, kScreenHeight); | |
278 | |
279 fProgram = this->setupShader(ctx, fCoverageSetup == kUseVec4_CoverageSetup); | |
280 | |
281 // setup matrices | |
tomhudson
2015/07/10 19:23:55
Useless comment.
What matrices? Why? Or eliminate!
wangyix
2015/07/13 17:29:52
Done.
| |
282 int index = 0; | |
283 SkMatrix viewMatrices[kNumTriPerDraw]; | |
284 setup_matrices(kNumTriPerDraw, [&index, &viewMatrices](const SkMatrix& m) { | |
285 viewMatrices[index++] = m; | |
286 }); | |
287 | |
288 // setup VAO | |
289 GR_GL_CALL(gl, GenVertexArrays(1, &fVAO)); | |
290 GR_GL_CALL(gl, BindVertexArray(fVAO)); | |
291 | |
292 this->setupSingleVbo(gl, viewMatrices); | |
293 | |
294 // set us up to draw | |
295 GR_GL_CALL(gl, UseProgram(fProgram)); | |
296 GR_GL_CALL(gl, BindVertexArray(fVAO)); | |
297 } | |
298 | |
299 void GLVec4ScalarBench::glDraw(const int loops, const GrGLContext* ctx) { | |
300 const GrGLInterface* gl = ctx->interface(); | |
301 | |
302 for (int i = 0; i < loops; i++) { | |
303 GR_GL_CALL(gl, DrawArrays(GR_GL_TRIANGLES, 0, kVerticesPerTri * kNumTriP erDraw)); | |
304 } | |
305 | |
306 | |
307 #if 0 | |
308 //const char* filename = "/data/local/tmp/out.png"; | |
tomhudson
2015/07/10 19:23:55
Delete commented-out code.
In theory you could pro
tomhudson
2015/07/13 16:00:13
Again: How is your #0 different than the command-l
wangyix
2015/07/13 17:29:53
Using -w when running nanobench does not write out
| |
309 SkString filename("out"); | |
310 filename.appendf("_%s.png", this->getName()); | |
311 DumpImage(gl, kScreenWidth, kScreenHeight, filename.c_str()); | |
312 #endif | |
313 } | |
314 | |
315 void GLVec4ScalarBench::teardown(const GrGLInterface* gl) { | |
316 GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, 0)); | |
317 GR_GL_CALL(gl, BindVertexArray(0)); | |
318 GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, 0)); | |
319 GR_GL_CALL(gl, BindFramebuffer(GR_GL_FRAMEBUFFER, 0)); | |
320 GR_GL_CALL(gl, DeleteTextures(1, &fTexture)); | |
321 GR_GL_CALL(gl, DeleteProgram(fProgram)); | |
322 GR_GL_CALL(gl, DeleteBuffers(1, &fVBO)); | |
323 GR_GL_CALL(gl, DeleteVertexArrays(1, &fVAO)); | |
324 } | |
325 | |
326 /////////////////////////////////////////////////////////////////////////////// | |
327 | |
328 DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseScalar_CoverageSe tup, 1) ) | |
329 DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseVec4_CoverageSetu p, 1) ) | |
330 DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseScalar_CoverageSe tup, 2) ) | |
331 DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseVec4_CoverageSetu p, 2) ) | |
332 DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseScalar_CoverageSe tup, 4) ) | |
333 DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseVec4_CoverageSetu p, 4) ) | |
334 DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseScalar_CoverageSe tup, 6) ) | |
335 DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseVec4_CoverageSetu p, 6) ) | |
336 DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseScalar_CoverageSe tup, 8) ) | |
337 DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseVec4_CoverageSetu p, 8) ) | |
338 | |
339 #endif | |
OLD | NEW |