joshualitt | f06c389 | 2015-07-01 06:20:13 -0700 | [diff] [blame] | 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" |
joshualitt | 74a07db | 2015-07-01 12:39:07 -0700 | [diff] [blame] | 11 | |
joshualitt | f06c389 | 2015-07-01 06:20:13 -0700 | [diff] [blame] | 12 | #if SK_SUPPORT_GPU |
joshualitt | 74a07db | 2015-07-01 12:39:07 -0700 | [diff] [blame] | 13 | #include "GLBench.h" |
joshualitt | f06c389 | 2015-07-01 06:20:13 -0700 | [diff] [blame] | 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 | #include <stdio.h> |
| 20 | |
| 21 | /* |
| 22 | * This is a native GL benchmark for determining the cost of uploading vertex attributes |
| 23 | */ |
joshualitt | 74a07db | 2015-07-01 12:39:07 -0700 | [diff] [blame] | 24 | class GLVertexAttributesBench : public GLBench { |
joshualitt | f06c389 | 2015-07-01 06:20:13 -0700 | [diff] [blame] | 25 | public: |
| 26 | GLVertexAttributesBench(uint32_t attribs) |
| 27 | : fTexture(0) |
| 28 | , fBuffers(0) |
| 29 | , fProgram(0) |
joshualitt | f06c389 | 2015-07-01 06:20:13 -0700 | [diff] [blame] | 30 | , fVBO(0) |
| 31 | , fAttribs(attribs) |
| 32 | , fStride(2 * sizeof(SkPoint) + fAttribs * sizeof(GrGLfloat) * 4) { |
| 33 | fName.appendf("GLVertexAttributesBench_%d", fAttribs); |
| 34 | } |
| 35 | |
| 36 | protected: |
| 37 | const char* onGetName() override { return fName.c_str(); } |
joshualitt | 74a07db | 2015-07-01 12:39:07 -0700 | [diff] [blame] | 38 | void setup(const GrGLContext*) override; |
| 39 | void glDraw(const int loops, const GrGLContext*) override; |
| 40 | void teardown(const GrGLInterface*) override; |
joshualitt | f06c389 | 2015-07-01 06:20:13 -0700 | [diff] [blame] | 41 | |
| 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 | |
| 49 | private: |
joshualitt | 74a07db | 2015-07-01 12:39:07 -0700 | [diff] [blame] | 50 | GrGLuint setupShader(const GrGLContext*, uint32_t attribs, uint32_t maxAttribs); |
| 51 | |
joshualitt | f06c389 | 2015-07-01 06:20:13 -0700 | [diff] [blame] | 52 | GrGLuint fTexture; |
| 53 | SkTArray<GrGLuint> fBuffers; |
| 54 | GrGLuint fProgram; |
joshualitt | f06c389 | 2015-07-01 06:20:13 -0700 | [diff] [blame] | 55 | GrGLuint fVBO; |
| 56 | SkTArray<unsigned char> fVertices; |
| 57 | uint32_t fAttribs; |
| 58 | size_t fStride; |
| 59 | SkString fName; |
| 60 | typedef Benchmark INHERITED; |
| 61 | }; |
| 62 | |
joshualitt | f06c389 | 2015-07-01 06:20:13 -0700 | [diff] [blame] | 63 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 64 | |
joshualitt | 74a07db | 2015-07-01 12:39:07 -0700 | [diff] [blame] | 65 | GrGLuint GLVertexAttributesBench::setupShader(const GrGLContext* ctx, uint32_t attribs, |
| 66 | uint32_t maxAttribs) { |
joshualitt | f06c389 | 2015-07-01 06:20:13 -0700 | [diff] [blame] | 67 | 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++) { |
joshualitt | bd929d9 | 2015-07-01 08:34:50 -0700 | [diff] [blame] | 110 | vshaderTxt.appendf("%s = vec4(0, 0, 0, 1);\n", oVars[i].c_str()); |
joshualitt | f06c389 | 2015-07-01 06:20:13 -0700 | [diff] [blame] | 111 | } |
| 112 | |
| 113 | vshaderTxt.append("}\n"); |
| 114 | |
| 115 | const GrGLInterface* gl = ctx->interface(); |
joshualitt | f06c389 | 2015-07-01 06:20:13 -0700 | [diff] [blame] | 116 | |
| 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 | |
joshualitt | 74a07db | 2015-07-01 12:39:07 -0700 | [diff] [blame] | 151 | return CreateProgram(gl, vshaderTxt.c_str(), fshaderTxt.c_str()); |
joshualitt | f06c389 | 2015-07-01 06:20:13 -0700 | [diff] [blame] | 152 | } |
| 153 | |
| 154 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 155 | |
| 156 | void GLVertexAttributesBench::setup(const GrGLContext* ctx) { |
| 157 | const GrGLInterface* gl = ctx->interface(); |
joshualitt | 74a07db | 2015-07-01 12:39:07 -0700 | [diff] [blame] | 158 | fTexture = SetupFramebuffer(gl, kScreenWidth, kScreenHeight); |
joshualitt | f06c389 | 2015-07-01 06:20:13 -0700 | [diff] [blame] | 159 | |
joshualitt | 74a07db | 2015-07-01 12:39:07 -0700 | [diff] [blame] | 160 | fProgram = setupShader(ctx, fAttribs, kMaxAttribs); |
joshualitt | f06c389 | 2015-07-01 06:20:13 -0700 | [diff] [blame] | 161 | |
| 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 | |
joshualitt | f06c389 | 2015-07-01 06:20:13 -0700 | [diff] [blame] | 170 | // 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)); |
joshualitt | f06c389 | 2015-07-01 06:20:13 -0700 | [diff] [blame] | 208 | } |
| 209 | |
joshualitt | 74a07db | 2015-07-01 12:39:07 -0700 | [diff] [blame] | 210 | void GLVertexAttributesBench::glDraw(const int loops, const GrGLContext* ctx) { |
joshualitt | f06c389 | 2015-07-01 06:20:13 -0700 | [diff] [blame] | 211 | 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 | |
joshualitt | 74a07db | 2015-07-01 12:39:07 -0700 | [diff] [blame] | 240 | #if 0 |
joshualitt | f06c389 | 2015-07-01 06:20:13 -0700 | [diff] [blame] | 241 | //const char* filename = "/data/local/tmp/out.png"; |
| 242 | SkString filename("out"); |
| 243 | filename.appendf("_%s.png", this->getName()); |
joshualitt | 74a07db | 2015-07-01 12:39:07 -0700 | [diff] [blame] | 244 | DumpImage(gl, kScreenWidth, kScreenHeight, filename.c_str()); |
joshualitt | f06c389 | 2015-07-01 06:20:13 -0700 | [diff] [blame] | 245 | #endif |
| 246 | } |
| 247 | |
joshualitt | 74a07db | 2015-07-01 12:39:07 -0700 | [diff] [blame] | 248 | void 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())); |
joshualitt | 31b21f6 | 2015-07-16 13:40:51 -0700 | [diff] [blame] | 256 | fBuffers.reset(); |
joshualitt | 74a07db | 2015-07-01 12:39:07 -0700 | [diff] [blame] | 257 | } |
joshualitt | f06c389 | 2015-07-01 06:20:13 -0700 | [diff] [blame] | 258 | |
| 259 | /////////////////////////////////////////////////////////////////////////////// |
| 260 | |
| 261 | DEF_BENCH( return new GLVertexAttributesBench(0) ) |
| 262 | DEF_BENCH( return new GLVertexAttributesBench(1) ) |
| 263 | DEF_BENCH( return new GLVertexAttributesBench(2) ) |
| 264 | DEF_BENCH( return new GLVertexAttributesBench(3) ) |
| 265 | DEF_BENCH( return new GLVertexAttributesBench(4) ) |
| 266 | DEF_BENCH( return new GLVertexAttributesBench(5) ) |
| 267 | DEF_BENCH( return new GLVertexAttributesBench(6) ) |
| 268 | DEF_BENCH( return new GLVertexAttributesBench(7) ) |
| 269 | #endif |