Chromium Code Reviews| Index: bench/GLVec4ScalarBench.cpp |
| diff --git a/bench/GLVec4ScalarBench.cpp b/bench/GLVec4ScalarBench.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..314bce3571e20ed0cd7b8829e3dfac6cc3b91af1 |
| --- /dev/null |
| +++ b/bench/GLVec4ScalarBench.cpp |
| @@ -0,0 +1,339 @@ |
| +/* |
| + * Copyright 2015 Google Inc. |
| + * |
| + * Use of this source code is governed by a BSD-style license that can be |
| + * found in the LICENSE file. |
| + */ |
| + |
| +#include "Benchmark.h" |
| +#include "SkCanvas.h" |
| +#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.
|
| + |
| +#if SK_SUPPORT_GPU |
| +#include "GLBench.h" |
| +#include "gl/GrGLGLSL.h" |
| +#include "gl/GrGLInterface.h" |
| +#include "gl/GrGLShaderVar.h" |
| +#include "gl/GrGLUtil.h" |
| +#include "glsl/GrGLSLCaps.h" |
| + |
| +#include <stdio.h> |
| + |
| +/* |
|
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.
|
| + * This is a native GL benchmark for instanced arrays vs vertex buffer objects. To benchmark this |
| + * functionality, we draw n * kDrawMultipier triangles per run. If this number is less than |
| + * kNumTri then we do a single draw, either with instances, or drawArrays. Otherwise we do |
| + * multiple draws. |
| + * |
| + * Additionally, there is a divisor, which if > 0 will act as a multiplier for the number of draws |
| + * issued. |
| + */ |
| + |
| +class GLVec4ScalarBench : public GLBench { |
| +public: |
| + /* |
| + * Use float or vec4 as GLSL data type for the output coverage |
| + */ |
| + enum CoverageSetup { |
| + kUseScalar_CoverageSetup, |
| + kUseVec4_CoverageSetup, |
| + }; |
| + |
| + /* |
| + * drawDiv will act as a multiplier for the number of draws we issue if > 0. ie, 2 will issue |
| + * 2x as many draws, 4 will issue 4x as many draws etc. There is a limit however, which is |
| + * 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.
|
| + */ |
| + GLVec4ScalarBench(CoverageSetup coverageSetup, uint32_t numStages) |
| + : fCoverageSetup(coverageSetup) |
| + , fNumStages(numStages) |
| + , fProgram(0) |
| + , fVAO(0) { |
|
tomhudson
2015/07/10 19:23:55
Why explicitly clear fVAO but not fVBO?
wangyix
2015/07/13 17:29:53
Done.
|
| + fName = CoverageSetupToStr(coverageSetup, numStages); |
| + } |
| + |
| +protected: |
| + const char* onGetName() override { |
| + return fName.c_str(); |
| + } |
| + |
| + 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
|
| + void setup(const GrGLContext*) override; |
| + void glDraw(const int loops, const GrGLContext*) override; |
| + void teardown(const GrGLInterface*) override; |
| + |
| +private: |
| + void setupSingleVbo(const GrGLInterface*, const SkMatrix*); |
| + GrGLuint setupShader(const GrGLContext*, bool useVec4ForCoverage); |
| + |
| + |
| + static SkString CoverageSetupToStr(CoverageSetup vboSetup, uint32_t numStages) { |
|
tomhudson
2015/07/10 19:23:55
Consider tweaking the function name, since you're
wangyix
2015/07/13 17:29:52
Done.
|
| + SkString name("GLVec4ScalarBench"); |
| + switch (vboSetup) { |
| + default: |
| + case kUseScalar_CoverageSetup: |
| + name.appendf("_scalar_%u_stage", numStages); |
| + break; |
| + case kUseVec4_CoverageSetup: |
| + name.appendf("_vec4_%u_stage", numStages); |
| + break; |
| + } |
| + return name; |
| + } |
| + |
| + static const GrGLuint kScreenWidth = 800; |
| + static const GrGLuint kScreenHeight = 600; |
| + static const uint32_t kNumTriPerDraw = 512; |
| + static const uint32_t kVerticesPerTri = 3; |
| + |
| + SkString fName; |
| + CoverageSetup fCoverageSetup; |
| + uint32_t fNumStages; |
| + 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
|
| + GrGLuint fProgram; |
| + GrGLuint fVAO; |
|
tomhudson
2015/07/10 19:23:55
... particularly when two abbreviations are very c
wangyix
2015/07/13 17:29:52
Done.
|
| + 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.
|
| +}; |
| + |
| +/////////////////////////////////////////////////////////////////////////////////////////////////// |
| + |
| +GrGLuint GLVec4ScalarBench::setupShader(const GrGLContext* ctx, bool useVec4ForCoverage) { |
|
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.
|
| + const char* version = GrGLGetGLSLVersionDecl(*ctx); |
| + |
| + // 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.
|
| + GrGLShaderVar aPosition("a_position", kVec2f_GrSLType, GrShaderVar::kAttribute_TypeModifier); |
| + GrGLShaderVar oPosition("o_position", kVec2f_GrSLType, GrShaderVar::kVaryingOut_TypeModifier); |
| + GrGLShaderVar aColor("a_color", kVec3f_GrSLType, GrShaderVar::kAttribute_TypeModifier); |
| + GrGLShaderVar oColor("o_color", kVec3f_GrSLType, GrShaderVar::kVaryingOut_TypeModifier); |
| + |
| + SkString vshaderTxt(version); |
| + aPosition.appendDecl(*ctx, &vshaderTxt); |
| + vshaderTxt.append(";\n"); |
| + aColor.appendDecl(*ctx, &vshaderTxt); |
| + vshaderTxt.append(";\n"); |
| + oPosition.appendDecl(*ctx, &vshaderTxt); |
| + vshaderTxt.append(";\n"); |
| + oColor.appendDecl(*ctx, &vshaderTxt); |
| + vshaderTxt.append(";\n"); |
| + |
| + vshaderTxt.append( |
| + "void main()\n" |
| + "{\n" |
| + " gl_Position = vec4(a_position, 0.f, 1.f);\n" |
| + " o_position = a_position;\n" |
| + " o_color = a_color;\n" |
| + "}\n"); |
| + |
| + const GrGLInterface* gl = ctx->interface(); |
| + |
| + // setup fragment shader |
| + GrGLShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_TypeModifier); |
| + SkString fshaderTxt(version); |
| + GrGLAppendGLSLDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, gl->fStandard, |
| + &fshaderTxt); |
| + oPosition.setTypeModifier(GrShaderVar::kVaryingIn_TypeModifier); |
| + oPosition.appendDecl(*ctx, &fshaderTxt); |
| + fshaderTxt.append(";\n"); |
| + oColor.setTypeModifier(GrShaderVar::kVaryingIn_TypeModifier); |
| + oColor.appendDecl(*ctx, &fshaderTxt); |
| + fshaderTxt.append(";\n"); |
| + |
| + const char* fsOutName; |
| + if (ctx->caps()->glslCaps()->mustDeclareFragmentShaderOutput()) { |
| + oFragColor.appendDecl(*ctx, &fshaderTxt); |
| + fshaderTxt.append(";\n"); |
| + fsOutName = oFragColor.c_str(); |
| + } else { |
| + fsOutName = "gl_FragColor"; |
| + } |
| + |
| + if (useVec4ForCoverage) { |
| + fshaderTxt.appendf( |
| + "void main()\n" |
| + "{\n" |
| + " vec4 outputColor;\n" |
| + " vec4 outputCoverage;\n" |
| + " outputColor = vec4(%s, 1.0);\n" |
| + " outputCoverage = vec4(1.0);\n", |
| + oColor.getName().c_str()); |
| + } else { |
| + fshaderTxt.appendf( |
| + "void main()\n" |
| + "{\n" |
| + " vec4 outputColor;\n" |
| + " float outputCoverage;\n" |
| + " outputColor = vec4(%s, 1.0);\n" |
| + " outputCoverage = 1.0;\n", |
| + oColor.getName().c_str()); |
| + } |
| + float radius = 1.0f; |
| + 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.
|
| + float centerX = 1.0f - radius; |
| + float centerY = 1.0f - radius; |
| + if (useVec4ForCoverage) { |
| + fshaderTxt.appendf( |
| + " {\n" |
| + " float d = length(%s - vec2(%f, %f));\n" |
| + " float edgeAlpha = clamp(100.0 * (%f - d), 0.0, 1.0);\n" |
| + " outputCoverage = 0.5 * outputCoverage + 0.5 * vec4(edgeAlpha);\n" |
| + " }\n", |
| + oPosition.getName().c_str(), |
| + centerX, centerY, |
| + radius |
| + ); |
| + } else { |
| + fshaderTxt.appendf( |
| + " {\n" |
| + " float d = length(%s - vec2(%f, %f));\n" |
| + " float edgeAlpha = clamp(100.0 * (%f - d), 0.0, 1.0);\n" |
| + " outputCoverage = 0.5 * outputCoverage + 0.5 * edgeAlpha;\n" |
| + " }\n", |
| + oPosition.getName().c_str(), |
| + centerX, centerY, |
| + radius |
| + ); |
| + } |
| + radius *= 0.8f; |
| + } |
| + fshaderTxt.appendf( |
| + " {\n" |
| + " %s = outputColor * outputCoverage;\n" |
| + " }\n" |
| + "}\n", |
| + fsOutName); |
| + |
| +//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.
|
| + |
| + return CreateProgram(gl, vshaderTxt.c_str(), fshaderTxt.c_str()); |
| +} |
| + |
| +template<typename Func> |
| +static void setup_matrices(int numQuads, Func f) { |
| + // We draw a really small triangle so we are not fill rate limited |
| + for (int i = 0 ; i < numQuads; i++) { |
| + SkMatrix m = SkMatrix::I(); |
| + m.setScale(0.01f, 0.01f); |
| + f(m); |
| + } |
| +} |
| + |
| +/////////////////////////////////////////////////////////////////////////////////////////////////// |
| + |
| +const GrGLContext* GLVec4ScalarBench::onGetGLContext(const GrGLContext* ctx) { |
| + // We only care about gpus with drawArraysInstanced support |
| + if (!ctx->interface()->fFunctions.fDrawArraysInstanced) { |
| + return NULL; |
| + } |
| + return ctx; |
| +} |
| + |
| +struct Vertex { |
| + SkPoint fPositions; |
| + GrGLfloat fColors[3]; |
| +}; |
| + |
| +void GLVec4ScalarBench::setupSingleVbo(const GrGLInterface* gl, |
| + const SkMatrix* viewMatrices) { |
|
tomhudson
2015/07/10 19:23:54
Nit: fix indentation
wangyix
2015/07/13 17:29:53
Done.
|
| + // 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.
|
| + Vertex vertices[kVerticesPerTri * kNumTriPerDraw]; |
| + for (uint32_t i = 0; i < kNumTriPerDraw; i++) { |
| + Vertex* v = &vertices[i * kVerticesPerTri]; |
| + if (i % 2 == 0) { |
| + v[0].fPositions.set(-1.0f, -1.0f); |
| + v[1].fPositions.set( 1.0f, -1.0f); |
| + v[2].fPositions.set( 1.0f, 1.0f); |
| + } else { |
| + v[0].fPositions.set(-1.0f, -1.0f); |
| + v[1].fPositions.set( 1.0f, 1.0f); |
| + v[2].fPositions.set( -1.0f, 1.0f); |
| + } |
| + SkPoint* position = reinterpret_cast<SkPoint*>(v); |
| + viewMatrices[i].mapPointsWithStride(position, sizeof(Vertex), kVerticesPerTri); |
| + |
| + // set colors |
|
tomhudson
2015/07/10 19:23:55
Bad evil comment. Expurgate!
wangyix
2015/07/13 17:29:53
Done.
|
| + GrGLfloat color[3] = {1.0f, 0.0f, 1.0f}; |
| + for (uint32_t j = 0; j < kVerticesPerTri; j++) { |
| + v->fColors[0] = color[0]; |
| + v->fColors[1] = color[1]; |
| + v->fColors[2] = color[2]; |
| + v++; |
| + } |
| + } |
| + |
| + // 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.
|
| + GR_GL_CALL(gl, GenBuffers(1, &fVBO)); |
| + GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, fVBO)); |
| + GR_GL_CALL(gl, EnableVertexAttribArray(0)); |
| + GR_GL_CALL(gl, EnableVertexAttribArray(1)); |
| + GR_GL_CALL(gl, VertexAttribPointer(0, 2, GR_GL_FLOAT, GR_GL_FALSE, sizeof(Vertex), |
| + (GrGLvoid*)0)); |
| + GR_GL_CALL(gl, VertexAttribPointer(1, 3, GR_GL_FLOAT, GR_GL_FALSE, sizeof(Vertex), |
| + (GrGLvoid*)(sizeof(SkPoint)))); |
| + GR_GL_CALL(gl, BufferData(GR_GL_ARRAY_BUFFER, sizeof(vertices), vertices, GR_GL_STATIC_DRAW)); |
| +} |
| + |
| +void GLVec4ScalarBench::setup(const GrGLContext* ctx) { |
| + const GrGLInterface* gl = ctx->interface(); |
| + fTexture = SetupFramebuffer(gl, kScreenWidth, kScreenHeight); |
| + |
| + fProgram = this->setupShader(ctx, fCoverageSetup == kUseVec4_CoverageSetup); |
| + |
| + // setup matrices |
|
tomhudson
2015/07/10 19:23:55
Useless comment.
What matrices? Why? Or eliminate!
wangyix
2015/07/13 17:29:52
Done.
|
| + int index = 0; |
| + SkMatrix viewMatrices[kNumTriPerDraw]; |
| + setup_matrices(kNumTriPerDraw, [&index, &viewMatrices](const SkMatrix& m) { |
| + viewMatrices[index++] = m; |
| + }); |
| + |
| + // setup VAO |
| + GR_GL_CALL(gl, GenVertexArrays(1, &fVAO)); |
| + GR_GL_CALL(gl, BindVertexArray(fVAO)); |
| + |
| + this->setupSingleVbo(gl, viewMatrices); |
| + |
| + // set us up to draw |
| + GR_GL_CALL(gl, UseProgram(fProgram)); |
| + GR_GL_CALL(gl, BindVertexArray(fVAO)); |
| +} |
| + |
| +void GLVec4ScalarBench::glDraw(const int loops, const GrGLContext* ctx) { |
| + const GrGLInterface* gl = ctx->interface(); |
| + |
| + for (int i = 0; i < loops; i++) { |
| + GR_GL_CALL(gl, DrawArrays(GR_GL_TRIANGLES, 0, kVerticesPerTri * kNumTriPerDraw)); |
| + } |
| + |
| + |
| +#if 0 |
| + //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
|
| + SkString filename("out"); |
| + filename.appendf("_%s.png", this->getName()); |
| + DumpImage(gl, kScreenWidth, kScreenHeight, filename.c_str()); |
| +#endif |
| +} |
| + |
| +void GLVec4ScalarBench::teardown(const GrGLInterface* gl) { |
| + GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, 0)); |
| + GR_GL_CALL(gl, BindVertexArray(0)); |
| + GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, 0)); |
| + GR_GL_CALL(gl, BindFramebuffer(GR_GL_FRAMEBUFFER, 0)); |
| + GR_GL_CALL(gl, DeleteTextures(1, &fTexture)); |
| + GR_GL_CALL(gl, DeleteProgram(fProgram)); |
| + GR_GL_CALL(gl, DeleteBuffers(1, &fVBO)); |
| + GR_GL_CALL(gl, DeleteVertexArrays(1, &fVAO)); |
| +} |
| + |
| +/////////////////////////////////////////////////////////////////////////////// |
| + |
| +DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseScalar_CoverageSetup, 1) ) |
| +DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseVec4_CoverageSetup, 1) ) |
| +DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseScalar_CoverageSetup, 2) ) |
| +DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseVec4_CoverageSetup, 2) ) |
| +DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseScalar_CoverageSetup, 4) ) |
| +DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseVec4_CoverageSetup, 4) ) |
| +DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseScalar_CoverageSetup, 6) ) |
| +DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseVec4_CoverageSetup, 6) ) |
| +DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseScalar_CoverageSetup, 8) ) |
| +DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseVec4_CoverageSetup, 8) ) |
| + |
| +#endif |