Chromium Code Reviews| 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 |