Home | History | Annotate | Download | only in bench
      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:
     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:
     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 
     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 
    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 
    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 
    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