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