| 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" | 
|  | 11 #if SK_SUPPORT_GPU | 
|  | 12 #include "GrTest.h" | 
|  | 13 #include "gl/GrGLGLSL.h" | 
|  | 14 #include "gl/GrGLInterface.h" | 
|  | 15 #include "gl/GrGLShaderVar.h" | 
|  | 16 #include "gl/GrGLUtil.h" | 
|  | 17 #include "glsl/GrGLSLCaps.h" | 
|  | 18 #include <stdio.h> | 
|  | 19 | 
|  | 20 /* | 
|  | 21  * This is a native GL benchmark for instanced arrays vs vertex buffer objects. 
      To benchmark this | 
|  | 22  * functionality, we draw n * kDrawMultipier triangles per run.  If this number 
     is less than | 
|  | 23  * kNumTri then we do a single draw, either with instances, or drawArrays.  Othe
     rwise we do | 
|  | 24  * multiple draws. | 
|  | 25  * | 
|  | 26  * Additionally, there is a divisor, which if > 0 will act as a multiplier for t
     he number of draws | 
|  | 27  * issued. | 
|  | 28  */ | 
|  | 29 class GLInstancedArraysBench : public Benchmark { | 
|  | 30 protected: | 
|  | 31     void onPerCanvasPreDraw(SkCanvas* canvas) override; | 
|  | 32     virtual void setup(const GrGLContext*)=0; | 
|  | 33     void onPerCanvasPostDraw(SkCanvas* canvas) override; | 
|  | 34     virtual void teardown(const GrGLInterface*)=0; | 
|  | 35 | 
|  | 36     static const GrGLuint kScreenWidth = 800; | 
|  | 37     static const GrGLuint kScreenHeight = 600; | 
|  | 38     static const uint32_t kNumTri = 10000; | 
|  | 39     static const uint32_t kVerticesPerTri = 3; | 
|  | 40     static const uint32_t kDrawMultiplier = 512; | 
|  | 41 | 
|  | 42 private: | 
|  | 43     GrGLuint fTexture; | 
|  | 44     typedef Benchmark INHERITED; | 
|  | 45 }; | 
|  | 46 | 
|  | 47 #if 0 | 
|  | 48 class GLGpuPosInstancedArraysBench : public GLInstancedArraysBench { | 
|  | 49 protected: | 
|  | 50     const char* onGetName() override { | 
|  | 51         return "GLInstancedArraysBench_gpupos"; | 
|  | 52     } | 
|  | 53 | 
|  | 54     void setup(const GrGLContext*) override; | 
|  | 55     void onDraw(const int loops, SkCanvas* canvas) override; | 
|  | 56 }; | 
|  | 57 #endif | 
|  | 58 | 
|  | 59 class GLCpuPosInstancedArraysBench : public GLInstancedArraysBench { | 
|  | 60 public: | 
|  | 61     /* | 
|  | 62      * Clients can decide to use either: | 
|  | 63      * kUseOne_VboSetup      - one vertex buffer with colors and positions inter
     leaved | 
|  | 64      * kUseTwo_VboSetup      - two vertex buffers, one for colors, one for posit
     ions | 
|  | 65      * kUseInstance_VboSetup - two vertex buffers, one with per vertex indices, 
     one with per | 
|  | 66      *                         instance colors | 
|  | 67      */ | 
|  | 68     enum VboSetup { | 
|  | 69         kUseOne_VboSetup, | 
|  | 70         kUseTwo_VboSetup, | 
|  | 71         kUseInstance_VboSetup, | 
|  | 72     }; | 
|  | 73 | 
|  | 74     /* | 
|  | 75      * drawDiv will act as a multiplier for the number of draws we issue if > 0.
      ie, 2 will issue | 
|  | 76      * 2x as many draws, 4 will issue 4x as many draws etc.  There is a limit ho
     wever, which is | 
|  | 77      * kDrawMultipier. | 
|  | 78      */ | 
|  | 79     GLCpuPosInstancedArraysBench(VboSetup vboSetup, int32_t drawDiv) | 
|  | 80         : fVboSetup(vboSetup) | 
|  | 81         , fDrawDiv(drawDiv) { | 
|  | 82         fName = VboSetupToStr(vboSetup, fDrawDiv); | 
|  | 83     } | 
|  | 84 | 
|  | 85 protected: | 
|  | 86     const char* onGetName() override { | 
|  | 87         return fName.c_str(); | 
|  | 88     } | 
|  | 89 | 
|  | 90     void setup(const GrGLContext*) override; | 
|  | 91     void onDraw(const int loops, SkCanvas* canvas) override; | 
|  | 92     void teardown(const GrGLInterface*) override; | 
|  | 93 | 
|  | 94 private: | 
|  | 95     void setupInstanceVbo(const GrGLInterface*, const SkMatrix*); | 
|  | 96     void setupDoubleVbo(const GrGLInterface*, const SkMatrix*); | 
|  | 97     void setupSingleVbo(const GrGLInterface*, const SkMatrix*); | 
|  | 98 | 
|  | 99     static SkString VboSetupToStr(VboSetup vboSetup, uint32_t drawDiv) { | 
|  | 100         SkString name("GLInstancedArraysBench"); | 
|  | 101         switch (vboSetup) { | 
|  | 102             default: | 
|  | 103             case kUseOne_VboSetup: | 
|  | 104                 name.appendf("_one_%u", drawDiv); | 
|  | 105                 break; | 
|  | 106             case kUseTwo_VboSetup: | 
|  | 107                 name.appendf("_two_%u", drawDiv); | 
|  | 108                 break; | 
|  | 109             case kUseInstance_VboSetup: | 
|  | 110                 name.append("_instance"); | 
|  | 111                 break; | 
|  | 112         } | 
|  | 113         return name; | 
|  | 114     } | 
|  | 115 | 
|  | 116     SkString fName; | 
|  | 117     VboSetup fVboSetup; | 
|  | 118     uint32_t fDrawDiv; | 
|  | 119     SkTArray<GrGLuint> fBuffers; | 
|  | 120     GrGLuint fProgram; | 
|  | 121     GrGLuint fVAO; | 
|  | 122 }; | 
|  | 123 | 
|  | 124 static const GrGLContext* get_gl_context(SkCanvas* canvas) { | 
|  | 125     // This bench exclusively tests GL calls directly | 
|  | 126     if (NULL == canvas->getGrContext()) { | 
|  | 127         return NULL; | 
|  | 128     } | 
|  | 129     GrContext* context = canvas->getGrContext(); | 
|  | 130 | 
|  | 131     GrTestTarget tt; | 
|  | 132     context->getTestTarget(&tt); | 
|  | 133     if (!tt.target()) { | 
|  | 134         SkDebugf("Couldn't get Gr test target."); | 
|  | 135         return NULL; | 
|  | 136     } | 
|  | 137 | 
|  | 138     const GrGLContext* ctx = tt.glContext(); | 
|  | 139     if (!ctx) { | 
|  | 140         SkDebugf("Couldn't get an interface\n"); | 
|  | 141         return NULL; | 
|  | 142     } | 
|  | 143 | 
|  | 144     // We only care about gpus with drawArraysInstanced support | 
|  | 145     if (!ctx->interface()->fFunctions.fDrawArraysInstanced) { | 
|  | 146         return NULL; | 
|  | 147     } | 
|  | 148     return ctx; | 
|  | 149 } | 
|  | 150 | 
|  | 151 void GLInstancedArraysBench::onPerCanvasPreDraw(SkCanvas* canvas) { | 
|  | 152     // This bench exclusively tests GL calls directly | 
|  | 153     const GrGLContext* ctx = get_gl_context(canvas); | 
|  | 154     if (!ctx) { | 
|  | 155         return; | 
|  | 156     } | 
|  | 157     this->setup(ctx); | 
|  | 158 } | 
|  | 159 | 
|  | 160 void GLInstancedArraysBench::onPerCanvasPostDraw(SkCanvas* canvas) { | 
|  | 161     // This bench exclusively tests GL calls directly | 
|  | 162     const GrGLContext* ctx = get_gl_context(canvas); | 
|  | 163     if (!ctx) { | 
|  | 164         return; | 
|  | 165     } | 
|  | 166 | 
|  | 167     const GrGLInterface* gl = ctx->interface(); | 
|  | 168 | 
|  | 169     // teardown | 
|  | 170     GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, 0)); | 
|  | 171     GR_GL_CALL(gl, BindVertexArray(0)); | 
|  | 172     GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, 0)); | 
|  | 173     GR_GL_CALL(gl, BindFramebuffer(GR_GL_FRAMEBUFFER, 0)); | 
|  | 174     GR_GL_CALL(gl, DeleteTextures(1, &fTexture)); | 
|  | 175 | 
|  | 176     this->teardown(gl); | 
|  | 177 } | 
|  | 178 | 
|  | 179 ////////////////////////////////////////////////////////////////////////////////
     /////////////////// | 
|  | 180 | 
|  | 181 // TODO move all of the gpu positioning stuff to a new file | 
|  | 182 #ifdef GPU_POS | 
|  | 183 static const char* gpu_vertex_shader = | 
|  | 184         "layout (location = 0) in vec2 position;\n" | 
|  | 185         "layout (location = 1) in vec3 color;\n" | 
|  | 186         "layout (location = 2) in mat3 offset;\n" | 
|  | 187 | 
|  | 188         "out vec3 fColor;\n" | 
|  | 189 | 
|  | 190         "void main()\n" | 
|  | 191         "{\n" | 
|  | 192             "gl_Position = vec4(offset * vec3(position, 1.0f), 1.f);\n" | 
|  | 193             "fColor = color;\n" | 
|  | 194         "}\n"; | 
|  | 195 #endif | 
|  | 196 | 
|  | 197 static GrGLuint load_shader(const GrGLInterface* gl, const char* shaderSrc, GrGL
     enum type) { | 
|  | 198     GrGLuint shader; | 
|  | 199     // Create the shader object | 
|  | 200     GR_GL_CALL_RET(gl, shader, CreateShader(type)); | 
|  | 201 | 
|  | 202     // Load the shader source | 
|  | 203     GR_GL_CALL(gl, ShaderSource(shader, 1, &shaderSrc, NULL)); | 
|  | 204 | 
|  | 205     // Compile the shader | 
|  | 206     GR_GL_CALL(gl, CompileShader(shader)); | 
|  | 207 | 
|  | 208     // Check for compile time errors | 
|  | 209     GrGLint success; | 
|  | 210     GrGLchar infoLog[512]; | 
|  | 211     GR_GL_CALL(gl, GetShaderiv(shader, GR_GL_COMPILE_STATUS, &success)); | 
|  | 212     if (!success) | 
|  | 213     { | 
|  | 214      GR_GL_CALL(gl, GetShaderInfoLog(shader, 512, NULL, infoLog)); | 
|  | 215      SkDebugf("ERROR::SHADER::COMPLIATION_FAILED: %s\n", infoLog); | 
|  | 216     } | 
|  | 217 | 
|  | 218     return shader; | 
|  | 219 } | 
|  | 220 | 
|  | 221 static GrGLuint compile_shader(const GrGLContext* ctx) { | 
|  | 222     const char* version = GrGLGetGLSLVersionDecl(*ctx); | 
|  | 223 | 
|  | 224     // setup vertex shader | 
|  | 225     GrGLShaderVar aPosition("a_position", kVec2f_GrSLType, GrShaderVar::kAttribu
     te_TypeModifier); | 
|  | 226     GrGLShaderVar aColor("a_color", kVec3f_GrSLType, GrShaderVar::kAttribute_Typ
     eModifier); | 
|  | 227     GrGLShaderVar oColor("o_color", kVec3f_GrSLType, GrShaderVar::kVaryingOut_Ty
     peModifier); | 
|  | 228 | 
|  | 229     SkString vshaderTxt(version); | 
|  | 230     aPosition.appendDecl(*ctx, &vshaderTxt); | 
|  | 231     vshaderTxt.append(";\n"); | 
|  | 232     aColor.appendDecl(*ctx, &vshaderTxt); | 
|  | 233     vshaderTxt.append(";\n"); | 
|  | 234     oColor.appendDecl(*ctx, &vshaderTxt); | 
|  | 235     vshaderTxt.append(";\n"); | 
|  | 236 | 
|  | 237     vshaderTxt.append( | 
|  | 238             "void main()\n" | 
|  | 239             "{\n" | 
|  | 240                 "gl_Position = vec4(a_position, 0.f, 1.f);\n" | 
|  | 241                 "o_color = a_color;\n" | 
|  | 242             "}\n"); | 
|  | 243 | 
|  | 244     const GrGLInterface* gl = ctx->interface(); | 
|  | 245     GrGLuint vertexShader = load_shader(gl, vshaderTxt.c_str(), GR_GL_VERTEX_SHA
     DER); | 
|  | 246 | 
|  | 247     // setup fragment shader | 
|  | 248     GrGLShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_T
     ypeModifier); | 
|  | 249     SkString fshaderTxt(version); | 
|  | 250     GrGLAppendGLSLDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, gl->f
     Standard, | 
|  | 251                                                    &fshaderTxt); | 
|  | 252     oColor.setTypeModifier(GrShaderVar::kVaryingIn_TypeModifier); | 
|  | 253     oColor.appendDecl(*ctx, &fshaderTxt); | 
|  | 254     fshaderTxt.append(";\n"); | 
|  | 255 | 
|  | 256     const char* fsOutName; | 
|  | 257     if (ctx->caps()->glslCaps()->mustDeclareFragmentShaderOutput()) { | 
|  | 258         oFragColor.appendDecl(*ctx, &fshaderTxt); | 
|  | 259         fshaderTxt.append(";\n"); | 
|  | 260         fsOutName = oFragColor.c_str(); | 
|  | 261     } else { | 
|  | 262         fsOutName = "gl_FragColor"; | 
|  | 263     } | 
|  | 264 | 
|  | 265     fshaderTxt.appendf( | 
|  | 266             "void main()\n" | 
|  | 267             "{\n" | 
|  | 268                 "%s = vec4(o_color, 1.0f);\n" | 
|  | 269             "}\n", fsOutName); | 
|  | 270 | 
|  | 271     GrGLuint fragmentShader = load_shader(gl, fshaderTxt.c_str(), GR_GL_FRAGMENT
     _SHADER); | 
|  | 272 | 
|  | 273     GrGLint shaderProgram; | 
|  | 274     GR_GL_CALL_RET(gl, shaderProgram, CreateProgram()); | 
|  | 275     GR_GL_CALL(gl, AttachShader(shaderProgram, vertexShader)); | 
|  | 276     GR_GL_CALL(gl, AttachShader(shaderProgram, fragmentShader)); | 
|  | 277     GR_GL_CALL(gl, LinkProgram(shaderProgram)); | 
|  | 278 | 
|  | 279     // Check for linking errors | 
|  | 280     GrGLint success; | 
|  | 281     GrGLchar infoLog[512]; | 
|  | 282     GR_GL_CALL(gl, GetProgramiv(shaderProgram, GR_GL_LINK_STATUS, &success)); | 
|  | 283     if (!success) { | 
|  | 284         GR_GL_CALL(gl, GetProgramInfoLog(shaderProgram, 512, NULL, infoLog)); | 
|  | 285         SkDebugf("Linker Error: %s\n", infoLog); | 
|  | 286     } | 
|  | 287     GR_GL_CALL(gl, DeleteShader(vertexShader)); | 
|  | 288     GR_GL_CALL(gl, DeleteShader(fragmentShader)); | 
|  | 289 | 
|  | 290     return shaderProgram; | 
|  | 291 } | 
|  | 292 | 
|  | 293 //#define DUMP_IMAGES | 
|  | 294 #ifdef DUMP_IMAGES | 
|  | 295 static void dump_image(const GrGLInterface* gl, uint32_t screenWidth, uint32_t s
     creenHeight, | 
|  | 296                        const char* filename) { | 
|  | 297     // read back pixels | 
|  | 298     uint32_t readback[screenWidth * screenHeight]; | 
|  | 299     GR_GL_CALL(gl, ReadPixels(0, // x | 
|  | 300                               0, // y | 
|  | 301                               screenWidth, // width | 
|  | 302                               screenHeight, // height | 
|  | 303                               GR_GL_RGBA, //format | 
|  | 304                               GR_GL_UNSIGNED_BYTE, //type | 
|  | 305                               readback)); | 
|  | 306 | 
|  | 307     // dump png | 
|  | 308     SkBitmap bm; | 
|  | 309     if (!bm.tryAllocPixels(SkImageInfo::MakeN32Premul(screenWidth, screenHeight)
     )) { | 
|  | 310         SkDebugf("couldn't allocate bitmap\n"); | 
|  | 311         return; | 
|  | 312     } | 
|  | 313 | 
|  | 314     bm.setPixels(readback); | 
|  | 315 | 
|  | 316     if (!SkImageEncoder::EncodeFile(filename, bm, SkImageEncoder::kPNG_Type, 100
     )) { | 
|  | 317         SkDebugf("------ failed to encode %s\n", filename); | 
|  | 318         remove(filename);   // remove any partial file | 
|  | 319         return; | 
|  | 320     } | 
|  | 321 } | 
|  | 322 #endif | 
|  | 323 | 
|  | 324 static void setup_framebuffer(const GrGLInterface* gl, int screenWidth, int scre
     enHeight) { | 
|  | 325     //Setup framebuffer | 
|  | 326     GrGLuint texture; | 
|  | 327     GR_GL_CALL(gl, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0)); | 
|  | 328     GR_GL_CALL(gl, PixelStorei(GR_GL_PACK_ROW_LENGTH, 0)); | 
|  | 329     GR_GL_CALL(gl, GenTextures(1, &texture)); | 
|  | 330     GR_GL_CALL(gl, ActiveTexture(GR_GL_TEXTURE15)); | 
|  | 331     GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, texture)); | 
|  | 332     GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MAG_FILTER, GR_
     GL_NEAREST)); | 
|  | 333     GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MIN_FILTER, GR_
     GL_NEAREST)); | 
|  | 334     GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_WRAP_S, GR_GL_C
     LAMP_TO_EDGE)); | 
|  | 335     GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_WRAP_T, GR_GL_C
     LAMP_TO_EDGE)); | 
|  | 336     GR_GL_CALL(gl, TexImage2D(GR_GL_TEXTURE_2D, | 
|  | 337                               0, //level | 
|  | 338                               GR_GL_RGBA8, //internal format | 
|  | 339                               screenWidth, // width | 
|  | 340                               screenHeight, // height | 
|  | 341                               0, //border | 
|  | 342                               GR_GL_RGBA, //format | 
|  | 343                               GR_GL_UNSIGNED_BYTE, // type | 
|  | 344                               NULL)); | 
|  | 345 | 
|  | 346     // bind framebuffer | 
|  | 347     GrGLuint framebuffer; | 
|  | 348     GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, 0)); | 
|  | 349     GR_GL_CALL(gl, GenFramebuffers(1, &framebuffer)); | 
|  | 350     GR_GL_CALL(gl, BindFramebuffer(GR_GL_FRAMEBUFFER, framebuffer)); | 
|  | 351     GR_GL_CALL(gl, FramebufferTexture2D(GR_GL_FRAMEBUFFER, | 
|  | 352                                         GR_GL_COLOR_ATTACHMENT0, | 
|  | 353                                         GR_GL_TEXTURE_2D, | 
|  | 354                                         texture, 0)); | 
|  | 355     GR_GL_CALL(gl, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); | 
|  | 356     GR_GL_CALL(gl, Viewport(0, 0, screenWidth, screenHeight)); | 
|  | 357 } | 
|  | 358 | 
|  | 359 template<typename Func> | 
|  | 360 static void setup_matrices(int numQuads, Func f) { | 
|  | 361 #if 0 | 
|  | 362     float max = sqrt(numQuads); | 
|  | 363     float pos = 1.f / (2 * max); | 
|  | 364     GrGLfloat offset = pos * 2; | 
|  | 365     for(GrGLint row = 0; row < max; row++) { | 
|  | 366         for(GrGLint col = 0; col < max; col++) { | 
|  | 367             SkScalar xOffset = col / max * 2.f - 1.f + offset; | 
|  | 368             SkScalar yOffset = row / max * 2.f - 1.f + offset; | 
|  | 369             SkMatrix translation; | 
|  | 370             SkRandom random; | 
|  | 371             translation.setScale(pos, pos); | 
|  | 372             translation.postTranslate(xOffset, yOffset); | 
|  | 373             f(translation); | 
|  | 374         } | 
|  | 375     } | 
|  | 376 #endif | 
|  | 377     // We draw a really small triangle so we are not fill rate limited | 
|  | 378     for (int i = 0 ; i < numQuads; i++) { | 
|  | 379         SkMatrix m = SkMatrix::I(); | 
|  | 380         m.setScale(0.0001f, 0.0001f); | 
|  | 381         f(m); | 
|  | 382     } | 
|  | 383 } | 
|  | 384 | 
|  | 385 #ifdef GPU_POS | 
|  | 386 void GLGpuPosInstancedArraysBench::setup(const GrGLInterface* gl) { | 
|  | 387     setup_framebuffer(gl, kScreenWidth, kScreenHeight); | 
|  | 388 | 
|  | 389     // compile and use shaders | 
|  | 390     GrGLint shaderProgram = compile_shader(gl, gpu_vertex_shader, fragment_shade
     r); | 
|  | 391 | 
|  | 392     // translations | 
|  | 393     int index = 0; | 
|  | 394     GrGLfloat viewMatrices[fNumQuads * fSkMatrixNumCells]; | 
|  | 395     setup_matrices(fNumQuads, [&index, &viewMatrices](const SkMatrix& m) { | 
|  | 396         GrGLGetMatrix<3>(&viewMatrices[index], m); | 
|  | 397         index += fSkMatrixNumCells; | 
|  | 398     }); | 
|  | 399 | 
|  | 400     // Constants for our various shader programs | 
|  | 401     GrGLfloat quad_vertices[] = { | 
|  | 402             // Positions // Colors | 
|  | 403             -1.0f,  1.0f,  1.0f, 0.0f, 0.0f, | 
|  | 404              1.0f, -1.0f,  0.0f, 1.0f, 0.0f, | 
|  | 405             -1.0f, -1.0f,  0.0f, 0.0f, 1.0f, | 
|  | 406 | 
|  | 407             -1.0f,  1.0f,  1.0f, 0.0f, 0.0f, | 
|  | 408              1.0f, -1.0f,  0.0f, 1.0f, 0.0f, | 
|  | 409              1.0f,  1.0f,  0.0f, 1.0f, 1.0f | 
|  | 410     }; | 
|  | 411 | 
|  | 412     // update vertex data | 
|  | 413     GrGLuint quadVAO, quadVBO; | 
|  | 414     GR_GL_CALL(gl, GenVertexArrays(1, &quadVAO)); | 
|  | 415     GR_GL_CALL(gl, GenBuffers(1, &quadVBO)); | 
|  | 416     GR_GL_CALL(gl, BindVertexArray(quadVAO)); | 
|  | 417     GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, quadVBO)); | 
|  | 418     GR_GL_CALL(gl, EnableVertexAttribArray(0)); | 
|  | 419     GR_GL_CALL(gl, VertexAttribPointer(0, 2, GR_GL_FLOAT, GR_GL_FALSE, 5 * sizeo
     f(GrGLfloat), (GrGLvoid*)0)); | 
|  | 420     GR_GL_CALL(gl, EnableVertexAttribArray(1)); | 
|  | 421     GR_GL_CALL(gl, VertexAttribPointer(1, 3, GR_GL_FLOAT, GR_GL_FALSE, 5 * sizeo
     f(GrGLfloat), (GrGLvoid*)(2 * sizeof(GrGLfloat)))); | 
|  | 422     GR_GL_CALL(gl, BufferData(GR_GL_ARRAY_BUFFER, sizeof(quad_vertices), quad_ve
     rtices, GR_GL_STATIC_DRAW)); | 
|  | 423 | 
|  | 424     // Also set instance data | 
|  | 425     GrGLuint instanceVBO; | 
|  | 426     GR_GL_CALL(gl, GenBuffers(1, &instanceVBO)); | 
|  | 427     GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, instanceVBO)); | 
|  | 428     GR_GL_CALL(gl, BufferData(GR_GL_ARRAY_BUFFER, sizeof(GrGLfloat) * fSkMatrixN
     umCells * fNumQuads, | 
|  | 429                               &viewMatrices[0], GR_GL_STATIC_DRAW)); | 
|  | 430     GR_GL_CALL(gl, EnableVertexAttribArray(2)); | 
|  | 431     GR_GL_CALL(gl, EnableVertexAttribArray(3)); | 
|  | 432     GR_GL_CALL(gl, EnableVertexAttribArray(4)); | 
|  | 433     GR_GL_CALL(gl, VertexAttribPointer(2, 3, GR_GL_FLOAT, GR_GL_FALSE, 9 * sizeo
     f(GrGLfloat), (GrGLvoid*)0)); | 
|  | 434     GR_GL_CALL(gl, VertexAttribPointer(3, 3, GR_GL_FLOAT, GR_GL_FALSE, 9 * sizeo
     f(GrGLfloat), (GrGLvoid*)(3 * sizeof(GrGLfloat)))); | 
|  | 435     GR_GL_CALL(gl, VertexAttribPointer(4, 3, GR_GL_FLOAT, GR_GL_FALSE, 9 * sizeo
     f(GrGLfloat), (GrGLvoid*)(6 * sizeof(GrGLfloat)))); | 
|  | 436     GR_GL_CALL(gl, VertexAttribDivisor(2, 1)); | 
|  | 437     GR_GL_CALL(gl, VertexAttribDivisor(3, 1)); | 
|  | 438     GR_GL_CALL(gl, VertexAttribDivisor(4, 1)); | 
|  | 439 | 
|  | 440     // draw | 
|  | 441     GR_GL_CALL(gl, ClearColor(0.03f, 0.03f, 0.03f, 1.0f)); | 
|  | 442     GR_GL_CALL(gl, Clear(GR_GL_COLOR_BUFFER_BIT)); | 
|  | 443 | 
|  | 444     // set us up to draw | 
|  | 445     GR_GL_CALL(gl, UseProgram(shaderProgram)); | 
|  | 446     GR_GL_CALL(gl, BindVertexArray(quadVAO)); | 
|  | 447 } | 
|  | 448 | 
|  | 449 void GLGpuPosInstancedArraysBench::onDraw(const int loops, SkCanvas* canvas) { | 
|  | 450     const GrGLInterface* gl = get_interface(canvas); | 
|  | 451     if (!gl) { | 
|  | 452         return; | 
|  | 453     } | 
|  | 454 | 
|  | 455     GR_GL_CALL(gl, DrawArraysInstanced(GR_GL_TRIANGLES, 0, 6, fNumQuads)); | 
|  | 456 | 
|  | 457 #ifdef DUMP_IMAGES | 
|  | 458     const char* filename = "out.png"; | 
|  | 459     dump_image(gl, kScreenWidth, kScreenHeight, filename); | 
|  | 460 #endif | 
|  | 461     SkFAIL("done\n"); | 
|  | 462 } | 
|  | 463 | 
|  | 464 static uint32_t setup_quad_index_buffer(const GrGLInterface* gl) { | 
|  | 465     static const int kMaxQuads = 1;//1 << 12; // max possible: (1 << 14) - 1; | 
|  | 466     GR_STATIC_ASSERT(4 * kMaxQuads <= 65535); | 
|  | 467     static const uint16_t kPattern[] = { 0, 1, 2, 0, 2, 3 }; | 
|  | 468     static const int kPatternSize = 6; | 
|  | 469     static const int kVertCount = 4; | 
|  | 470     static const int kIndicesCount = kPatternSize * kMaxQuads; | 
|  | 471     int size = kPatternSize * kMaxQuads * sizeof(uint16_t); | 
|  | 472 | 
|  | 473     uint16_t* data = SkNEW_ARRAY(uint16_t, kMaxQuads * kPatternSize); | 
|  | 474 | 
|  | 475     for (int i = 0; i < kMaxQuads; ++i) { | 
|  | 476         int baseIdx = i * kPatternSize; | 
|  | 477         uint16_t baseVert = (uint16_t)(i * kVertCount); | 
|  | 478         for (int j = 0; j < kPatternSize; ++j) { | 
|  | 479             data[baseIdx+j] = baseVert + kPattern[j]; | 
|  | 480         } | 
|  | 481     } | 
|  | 482 | 
|  | 483     GrGLuint quadIBO; | 
|  | 484     GR_GL_CALL(gl, GenBuffers(1, &quadIBO)); | 
|  | 485     GR_GL_CALL(gl, BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, quadIBO)); | 
|  | 486     GR_GL_CALL(gl, BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, size, data, GR_GL_STAT
     IC_DRAW)); | 
|  | 487 | 
|  | 488     SkDELETE_ARRAY(data); | 
|  | 489     return kIndicesCount; | 
|  | 490 } | 
|  | 491 #endif | 
|  | 492 | 
|  | 493 ////////////////////////////////////////////////////////////////////////////////
     /////////////////// | 
|  | 494 | 
|  | 495 void GLCpuPosInstancedArraysBench::setupInstanceVbo(const GrGLInterface* gl, | 
|  | 496                                                     const SkMatrix* viewMatrices
     ) { | 
|  | 497     // We draw all of the instances at a single place because we aren't allowed 
     to have per vertex | 
|  | 498     // per instance attributes | 
|  | 499     SkPoint positions[kVerticesPerTri]; | 
|  | 500     positions[0].set(-1.0f, -1.0f); | 
|  | 501     positions[1].set( 1.0f, -1.0f); | 
|  | 502     positions[2].set( 1.0f,  1.0f); | 
|  | 503     viewMatrices[0].mapPointsWithStride(positions, sizeof(SkPoint), kVerticesPer
     Tri); | 
|  | 504 | 
|  | 505     // setup colors so we can detect we are actually drawing instances(the last 
     triangle will be | 
|  | 506     // a different color) | 
|  | 507     GrGLfloat colors[kVerticesPerTri * kNumTri]; | 
|  | 508     for (uint32_t i = 0; i < kNumTri; i++) { | 
|  | 509         // set colors | 
|  | 510         uint32_t offset = i * kVerticesPerTri; | 
|  | 511         float color = i == kNumTri - 1 ? 1.0f : 0.0f; | 
|  | 512         colors[offset++] = color; colors[offset++] = 0.0f; colors[offset++] = 0.
     0f; | 
|  | 513     } | 
|  | 514 | 
|  | 515     GrGLuint posVBO; | 
|  | 516     // setup position VBO | 
|  | 517     GR_GL_CALL(gl, GenBuffers(1, &posVBO)); | 
|  | 518     GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, posVBO)); | 
|  | 519     GR_GL_CALL(gl, BufferData(GR_GL_ARRAY_BUFFER, sizeof(positions), positions, 
     GR_GL_STATIC_DRAW)); | 
|  | 520     GR_GL_CALL(gl, EnableVertexAttribArray(0)); | 
|  | 521     GR_GL_CALL(gl, VertexAttribPointer(0, 2, GR_GL_FLOAT, GR_GL_FALSE, 2 * sizeo
     f(GrGLfloat), | 
|  | 522                                        (GrGLvoid*)0)); | 
|  | 523 | 
|  | 524     // setup color VBO | 
|  | 525     GrGLuint instanceVBO; | 
|  | 526     GR_GL_CALL(gl, GenBuffers(1, &instanceVBO)); | 
|  | 527     GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, instanceVBO)); | 
|  | 528     GR_GL_CALL(gl, BufferData(GR_GL_ARRAY_BUFFER, sizeof(colors), colors, GR_GL_
     STATIC_DRAW)); | 
|  | 529     GR_GL_CALL(gl, EnableVertexAttribArray(1)); | 
|  | 530     GR_GL_CALL(gl, VertexAttribPointer(1, 3, GR_GL_FLOAT, GR_GL_FALSE, 3 * sizeo
     f(GrGLfloat), | 
|  | 531                                        (GrGLvoid*)0)); | 
|  | 532     GR_GL_CALL(gl, VertexAttribDivisor(1, 1)); | 
|  | 533     fBuffers.push_back(posVBO); | 
|  | 534     fBuffers.push_back(instanceVBO); | 
|  | 535 } | 
|  | 536 | 
|  | 537 void GLCpuPosInstancedArraysBench::setupDoubleVbo(const GrGLInterface* gl, | 
|  | 538                                                   const SkMatrix* viewMatrices) 
     { | 
|  | 539     // Constants for our various shader programs | 
|  | 540     SkPoint positions[kVerticesPerTri * kNumTri]; | 
|  | 541     GrGLfloat colors[kVerticesPerTri * kNumTri * 3]; | 
|  | 542     for (uint32_t i = 0; i < kNumTri; i++) { | 
|  | 543         SkPoint* position = &positions[i * kVerticesPerTri]; | 
|  | 544         position[0].set(-1.0f, -1.0f); | 
|  | 545         position[1].set( 1.0f, -1.0f); | 
|  | 546         position[2].set( 1.0f,  1.0f); | 
|  | 547         viewMatrices[i].mapPointsWithStride(position, sizeof(SkPoint), kVertices
     PerTri); | 
|  | 548 | 
|  | 549         // set colors | 
|  | 550         float color = i == kNumTri - 1 ? 1.0f : 0.0f; | 
|  | 551         uint32_t offset = i * kVerticesPerTri * 3; | 
|  | 552         for (uint32_t j = 0; j < kVerticesPerTri; j++) { | 
|  | 553             colors[offset++] = color; colors[offset++] = 0.0f; colors[offset++] 
     = 0.0f; | 
|  | 554         } | 
|  | 555     } | 
|  | 556 | 
|  | 557     GrGLuint posVBO, colorVBO; | 
|  | 558     // setup position VBO | 
|  | 559     GR_GL_CALL(gl, GenBuffers(1, &posVBO)); | 
|  | 560     GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, posVBO)); | 
|  | 561     GR_GL_CALL(gl, EnableVertexAttribArray(0)); | 
|  | 562     GR_GL_CALL(gl, VertexAttribPointer(0, 2, GR_GL_FLOAT, GR_GL_FALSE, 2 * sizeo
     f(GrGLfloat), | 
|  | 563                                        (GrGLvoid*)0)); | 
|  | 564     GR_GL_CALL(gl, BufferData(GR_GL_ARRAY_BUFFER, sizeof(positions), positions, 
     GR_GL_STATIC_DRAW)); | 
|  | 565 | 
|  | 566     // setup color VBO | 
|  | 567     GR_GL_CALL(gl, GenBuffers(1, &colorVBO)); | 
|  | 568     GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, colorVBO)); | 
|  | 569     GR_GL_CALL(gl, EnableVertexAttribArray(1)); | 
|  | 570     GR_GL_CALL(gl, VertexAttribPointer(1, 3, GR_GL_FLOAT, GR_GL_FALSE, 3 * sizeo
     f(GrGLfloat), | 
|  | 571                                        (GrGLvoid*)0)); | 
|  | 572     GR_GL_CALL(gl, BufferData(GR_GL_ARRAY_BUFFER, sizeof(colors), colors, GR_GL_
     STATIC_DRAW)); | 
|  | 573 | 
|  | 574     fBuffers.push_back(posVBO); | 
|  | 575     fBuffers.push_back(colorVBO); | 
|  | 576 } | 
|  | 577 | 
|  | 578 struct Vertex { | 
|  | 579     SkPoint fPositions; | 
|  | 580     GrGLfloat fColors[3]; | 
|  | 581 }; | 
|  | 582 | 
|  | 583 void GLCpuPosInstancedArraysBench::setupSingleVbo(const GrGLInterface* gl, | 
|  | 584                                                   const SkMatrix* viewMatrices) 
     { | 
|  | 585     // Constants for our various shader programs | 
|  | 586     Vertex vertices[kVerticesPerTri * kNumTri]; | 
|  | 587     for (uint32_t i = 0; i < kNumTri; i++) { | 
|  | 588         Vertex* v = &vertices[i * kVerticesPerTri]; | 
|  | 589         v[0].fPositions.set(-1.0f, -1.0f); | 
|  | 590         v[1].fPositions.set( 1.0f, -1.0f); | 
|  | 591         v[2].fPositions.set( 1.0f,  1.0f); | 
|  | 592 | 
|  | 593         SkPoint* position = reinterpret_cast<SkPoint*>(v); | 
|  | 594         viewMatrices[i].mapPointsWithStride(position, sizeof(Vertex), kVerticesP
     erTri); | 
|  | 595 | 
|  | 596         // set colors | 
|  | 597         float color = i == kNumTri - 1 ? 1.0f : 0.0f; | 
|  | 598         for (uint32_t j = 0; j < kVerticesPerTri; j++) { | 
|  | 599             uint32_t offset = 0; | 
|  | 600             v->fColors[offset++] = color; v->fColors[offset++] = 0.0f; v->fColor
     s[offset++] = 0.0f; | 
|  | 601             v++; | 
|  | 602         } | 
|  | 603     } | 
|  | 604 | 
|  | 605     GrGLuint vbo; | 
|  | 606     // setup VBO | 
|  | 607     GR_GL_CALL(gl, GenBuffers(1, &vbo)); | 
|  | 608     GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, vbo)); | 
|  | 609     GR_GL_CALL(gl, EnableVertexAttribArray(0)); | 
|  | 610     GR_GL_CALL(gl, EnableVertexAttribArray(1)); | 
|  | 611     GR_GL_CALL(gl, VertexAttribPointer(0, 2, GR_GL_FLOAT, GR_GL_FALSE, sizeof(Ve
     rtex), | 
|  | 612                                        (GrGLvoid*)0)); | 
|  | 613     GR_GL_CALL(gl, VertexAttribPointer(1, 3, GR_GL_FLOAT, GR_GL_FALSE, sizeof(Ve
     rtex), | 
|  | 614                                        (GrGLvoid*)(sizeof(SkPoint)))); | 
|  | 615     GR_GL_CALL(gl, BufferData(GR_GL_ARRAY_BUFFER, sizeof(vertices), vertices, GR
     _GL_STATIC_DRAW)); | 
|  | 616     fBuffers.push_back(vbo); | 
|  | 617 } | 
|  | 618 | 
|  | 619 void GLCpuPosInstancedArraysBench::setup(const GrGLContext* ctx) { | 
|  | 620     const GrGLInterface* gl = ctx->interface(); | 
|  | 621     setup_framebuffer(gl, kScreenWidth, kScreenHeight); | 
|  | 622 | 
|  | 623     fProgram = compile_shader(ctx); | 
|  | 624 | 
|  | 625     // setup matrices | 
|  | 626     int index = 0; | 
|  | 627     SkMatrix viewMatrices[kNumTri]; | 
|  | 628     setup_matrices(kNumTri, [&index, &viewMatrices](const SkMatrix& m) { | 
|  | 629         viewMatrices[index++] = m; | 
|  | 630     }); | 
|  | 631 | 
|  | 632     // setup VAO | 
|  | 633     GR_GL_CALL(gl, GenVertexArrays(1, &fVAO)); | 
|  | 634     GR_GL_CALL(gl, BindVertexArray(fVAO)); | 
|  | 635 | 
|  | 636     switch (fVboSetup) { | 
|  | 637         case kUseOne_VboSetup: | 
|  | 638             this->setupSingleVbo(gl, viewMatrices); | 
|  | 639             break; | 
|  | 640         case kUseTwo_VboSetup: | 
|  | 641             this->setupDoubleVbo(gl, viewMatrices); | 
|  | 642             break; | 
|  | 643         case kUseInstance_VboSetup: | 
|  | 644             this->setupInstanceVbo(gl, viewMatrices); | 
|  | 645             break; | 
|  | 646     } | 
|  | 647 | 
|  | 648     // clear screen | 
|  | 649     GR_GL_CALL(gl, ClearColor(0.03f, 0.03f, 0.03f, 1.0f)); | 
|  | 650     GR_GL_CALL(gl, Clear(GR_GL_COLOR_BUFFER_BIT)); | 
|  | 651 | 
|  | 652     // set us up to draw | 
|  | 653     GR_GL_CALL(gl, UseProgram(fProgram)); | 
|  | 654     GR_GL_CALL(gl, BindVertexArray(fVAO)); | 
|  | 655 } | 
|  | 656 | 
|  | 657 void GLCpuPosInstancedArraysBench::onDraw(const int loops, SkCanvas* canvas) { | 
|  | 658     const GrGLContext* ctx = get_gl_context(canvas); | 
|  | 659     if (!ctx) { | 
|  | 660         return; | 
|  | 661     } | 
|  | 662 | 
|  | 663     const GrGLInterface* gl = ctx->interface(); | 
|  | 664 | 
|  | 665     uint32_t maxTrianglesPerFlush = fDrawDiv == 0 ?  kNumTri : | 
|  | 666                                                      kDrawMultiplier / fDrawDiv; | 
|  | 667     uint32_t trianglesToDraw = loops * kDrawMultiplier; | 
|  | 668 | 
|  | 669     if (kUseInstance_VboSetup == fVboSetup) { | 
|  | 670         while (trianglesToDraw > 0) { | 
|  | 671             uint32_t triangles = SkTMin(trianglesToDraw, maxTrianglesPerFlush); | 
|  | 672             GR_GL_CALL(gl, DrawArraysInstanced(GR_GL_TRIANGLES, 0, kVerticesPerT
     ri, triangles)); | 
|  | 673             trianglesToDraw -= triangles; | 
|  | 674         } | 
|  | 675     } else { | 
|  | 676         while (trianglesToDraw > 0) { | 
|  | 677             uint32_t triangles = SkTMin(trianglesToDraw, maxTrianglesPerFlush); | 
|  | 678             GR_GL_CALL(gl, DrawArrays(GR_GL_TRIANGLES, 0, kVerticesPerTri * tria
     ngles)); | 
|  | 679             trianglesToDraw -= triangles; | 
|  | 680         } | 
|  | 681     } | 
|  | 682 | 
|  | 683 #ifdef DUMP_IMAGES | 
|  | 684     //const char* filename = "/data/local/tmp/out.png"; | 
|  | 685     SkString filename("out"); | 
|  | 686     filename.appendf("_%s.png", this->getName()); | 
|  | 687     dump_image(gl, kScreenWidth, kScreenHeight, filename.c_str()); | 
|  | 688 #endif | 
|  | 689 } | 
|  | 690 | 
|  | 691 void GLCpuPosInstancedArraysBench::teardown(const GrGLInterface* gl) { | 
|  | 692     GR_GL_CALL(gl, DeleteProgram(fProgram)); | 
|  | 693     GR_GL_CALL(gl, DeleteBuffers(fBuffers.count(), fBuffers.begin())); | 
|  | 694     GR_GL_CALL(gl, DeleteVertexArrays(1, &fVAO)); | 
|  | 695 } | 
|  | 696 | 
|  | 697 /////////////////////////////////////////////////////////////////////////////// | 
|  | 698 | 
|  | 699 DEF_BENCH( return new GLCpuPosInstancedArraysBench(GLCpuPosInstancedArraysBench:
     :kUseInstance_VboSetup, 0) ) | 
|  | 700 DEF_BENCH( return new GLCpuPosInstancedArraysBench(GLCpuPosInstancedArraysBench:
     :kUseOne_VboSetup, 0) ) | 
|  | 701 DEF_BENCH( return new GLCpuPosInstancedArraysBench(GLCpuPosInstancedArraysBench:
     :kUseTwo_VboSetup, 0) ) | 
|  | 702 DEF_BENCH( return new GLCpuPosInstancedArraysBench(GLCpuPosInstancedArraysBench:
     :kUseOne_VboSetup, 1) ) | 
|  | 703 DEF_BENCH( return new GLCpuPosInstancedArraysBench(GLCpuPosInstancedArraysBench:
     :kUseTwo_VboSetup, 1) ) | 
|  | 704 DEF_BENCH( return new GLCpuPosInstancedArraysBench(GLCpuPosInstancedArraysBench:
     :kUseOne_VboSetup, 2) ) | 
|  | 705 DEF_BENCH( return new GLCpuPosInstancedArraysBench(GLCpuPosInstancedArraysBench:
     :kUseTwo_VboSetup, 2) ) | 
|  | 706 DEF_BENCH( return new GLCpuPosInstancedArraysBench(GLCpuPosInstancedArraysBench:
     :kUseOne_VboSetup, 4) ) | 
|  | 707 DEF_BENCH( return new GLCpuPosInstancedArraysBench(GLCpuPosInstancedArraysBench:
     :kUseTwo_VboSetup, 4) ) | 
|  | 708 DEF_BENCH( return new GLCpuPosInstancedArraysBench(GLCpuPosInstancedArraysBench:
     :kUseOne_VboSetup, 8) ) | 
|  | 709 DEF_BENCH( return new GLCpuPosInstancedArraysBench(GLCpuPosInstancedArraysBench:
     :kUseTwo_VboSetup, 8) ) | 
|  | 710 | 
|  | 711 #endif | 
| OLD | NEW | 
|---|