Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(34)

Side by Side Diff: bench/GLVertexAttributesBench.cpp

Issue 1213233011: Benchmark to test cost for additional vertex attributes (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: tweaks Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 determining the cost of uploading vertex at tributes
22 */
23 class GLVertexAttributesBench : public Benchmark {
24 public:
25 GLVertexAttributesBench(uint32_t attribs)
26 : fTexture(0)
27 , fBuffers(0)
28 , fProgram(0)
29 , fVAO(0)
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(); }
38 void onPerCanvasPreDraw(SkCanvas* canvas) override;
39 void setup(const GrGLContext*);
40 void onDraw(const int loops, SkCanvas*) override;
41 void onPerCanvasPostDraw(SkCanvas* canvas) 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 fTexture;
52 SkTArray<GrGLuint> fBuffers;
53 GrGLuint fProgram;
54 GrGLuint fVAO;
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
63 static const GrGLContext* get_gl_context(SkCanvas* canvas) {
64 // This bench exclusively tests GL calls directly
65 if (NULL == canvas->getGrContext()) {
66 return NULL;
67 }
68 GrContext* context = canvas->getGrContext();
69
70 GrTestTarget tt;
71 context->getTestTarget(&tt);
72 if (!tt.target()) {
73 SkDebugf("Couldn't get Gr test target.");
74 return NULL;
75 }
76
77 const GrGLContext* ctx = tt.glContext();
78 if (!ctx) {
79 SkDebugf("Couldn't get an interface\n");
80 return NULL;
81 }
82
83 return ctx;
84 }
85
86 void GLVertexAttributesBench::onPerCanvasPreDraw(SkCanvas* canvas) {
87 // This bench exclusively tests GL calls directly
88 const GrGLContext* ctx = get_gl_context(canvas);
89 if (!ctx) {
90 return;
91 }
92 this->setup(ctx);
93 }
94
95 void GLVertexAttributesBench::onPerCanvasPostDraw(SkCanvas* canvas) {
96 // This bench exclusively tests GL calls directly
97 const GrGLContext* ctx = get_gl_context(canvas);
98 if (!ctx) {
99 return;
100 }
101
102 const GrGLInterface* gl = ctx->interface();
103
104 // teardown
105 GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, 0));
106 GR_GL_CALL(gl, BindVertexArray(0));
107 GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, 0));
108 GR_GL_CALL(gl, BindFramebuffer(GR_GL_FRAMEBUFFER, 0));
109 GR_GL_CALL(gl, DeleteTextures(1, &fTexture));
110 GR_GL_CALL(gl, DeleteProgram(fProgram));
111 GR_GL_CALL(gl, DeleteBuffers(fBuffers.count(), fBuffers.begin()));
112 GR_GL_CALL(gl, DeleteVertexArrays(1, &fVAO));
113 }
114
115 //////////////////////////////////////////////////////////////////////////////// ///////////////////
116
117 static GrGLuint load_shader(const GrGLInterface* gl, const char* shaderSrc, GrGL enum type) {
118 GrGLuint shader;
119 // Create the shader object
120 GR_GL_CALL_RET(gl, shader, CreateShader(type));
121
122 // Load the shader source
123 GR_GL_CALL(gl, ShaderSource(shader, 1, &shaderSrc, NULL));
124
125 // Compile the shader
126 GR_GL_CALL(gl, CompileShader(shader));
127
128 // Check for compile time errors
129 GrGLint success;
130 GrGLchar infoLog[512];
131 GR_GL_CALL(gl, GetShaderiv(shader, GR_GL_COMPILE_STATUS, &success));
132 if (!success) {
133 GR_GL_CALL(gl, GetShaderInfoLog(shader, 512, NULL, infoLog));
134 SkDebugf("ERROR::SHADER::COMPLIATION_FAILED: %s\n", infoLog);
135 }
136
137 return shader;
138 }
139
140 static GrGLuint compile_shader(const GrGLContext* ctx, uint32_t attribs, uint32_ t maxAttribs) {
141 const char* version = GrGLGetGLSLVersionDecl(*ctx);
142
143 // setup vertex shader
144 GrGLShaderVar aPosition("a_position", kVec4f_GrSLType, GrShaderVar::kAttribu te_TypeModifier);
145 SkTArray<GrGLShaderVar> aVars;
146 SkTArray<GrGLShaderVar> oVars;
147
148 SkString vshaderTxt(version);
149 aPosition.appendDecl(*ctx, &vshaderTxt);
150 vshaderTxt.append(";\n");
151
152 for (uint32_t i = 0; i < attribs; i++) {
153 SkString aname;
154 aname.appendf("a_color_%d", i);
155 aVars.push_back(GrGLShaderVar(aname.c_str(),
156 kVec4f_GrSLType,
157 GrShaderVar::kAttribute_TypeModifier));
158 aVars.back().appendDecl(*ctx, &vshaderTxt);
159 vshaderTxt.append(";\n");
160
161 }
162
163 for (uint32_t i = 0; i < maxAttribs; i++) {
164 SkString oname;
165 oname.appendf("o_color_%d", i);
166 oVars.push_back(GrGLShaderVar(oname.c_str(),
167 kVec4f_GrSLType,
168 GrShaderVar::kVaryingOut_TypeModifier));
169 oVars.back().appendDecl(*ctx, &vshaderTxt);
170 vshaderTxt.append(";\n");
171 }
172
173 vshaderTxt.append(
174 "void main()\n"
175 "{\n"
176 "gl_Position = a_position;\n");
177
178 for (uint32_t i = 0; i < attribs; i++) {
179 vshaderTxt.appendf("%s = %s;\n", oVars[i].c_str(), aVars[i].c_str());
180 }
181
182 // Passthrough position as a dummy
183 for (uint32_t i = attribs; i < maxAttribs; i++) {
184 vshaderTxt.appendf("%s = vec4(0.f, 0.f, 0.f, 1.f);\n", oVars[i].c_str()) ;
185 }
186
187 vshaderTxt.append("}\n");
188
189 const GrGLInterface* gl = ctx->interface();
190 GrGLuint vertexShader = load_shader(gl, vshaderTxt.c_str(), GR_GL_VERTEX_SHA DER);
191
192 // setup fragment shader
193 GrGLShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_T ypeModifier);
194 SkString fshaderTxt(version);
195 GrGLAppendGLSLDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, gl->f Standard,
196 &fshaderTxt);
197
198 const char* fsOutName;
199 if (ctx->caps()->glslCaps()->mustDeclareFragmentShaderOutput()) {
200 oFragColor.appendDecl(*ctx, &fshaderTxt);
201 fshaderTxt.append(";\n");
202 fsOutName = oFragColor.c_str();
203 } else {
204 fsOutName = "gl_FragColor";
205 }
206
207 for (uint32_t i = 0; i < maxAttribs; i++) {
208 oVars[i].setTypeModifier(GrShaderVar::kVaryingIn_TypeModifier);
209 oVars[i].appendDecl(*ctx, &fshaderTxt);
210 fshaderTxt.append(";\n");
211 }
212
213 fshaderTxt.appendf(
214 "void main()\n"
215 "{\n"
216 "%s = ", fsOutName);
217
218 fshaderTxt.appendf("%s", oVars[0].c_str());
219 for (uint32_t i = 1; i < maxAttribs; i++) {
220 fshaderTxt.appendf(" + %s", oVars[i].c_str());
221 }
222
223 fshaderTxt.append(";\n"
224 "}\n");
225
226 GrGLuint fragmentShader = load_shader(gl, fshaderTxt.c_str(), GR_GL_FRAGMENT _SHADER);
227
228 GrGLint shaderProgram;
229 GR_GL_CALL_RET(gl, shaderProgram, CreateProgram());
230 GR_GL_CALL(gl, AttachShader(shaderProgram, vertexShader));
231 GR_GL_CALL(gl, AttachShader(shaderProgram, fragmentShader));
232 GR_GL_CALL(gl, LinkProgram(shaderProgram));
233
234 // Check for linking errors
235 GrGLint success;
236 GrGLchar infoLog[512];
237 GR_GL_CALL(gl, GetProgramiv(shaderProgram, GR_GL_LINK_STATUS, &success));
238 if (!success) {
239 GR_GL_CALL(gl, GetProgramInfoLog(shaderProgram, 512, NULL, infoLog));
240 SkDebugf("Linker Error: %s\n", infoLog);
241 }
242 GR_GL_CALL(gl, DeleteShader(vertexShader));
243 GR_GL_CALL(gl, DeleteShader(fragmentShader));
244
245 return shaderProgram;
246 }
247
248 //#define DUMP_IMAGES
249 #ifdef DUMP_IMAGES
250 static void dump_image(const GrGLInterface* gl, uint32_t screenWidth, uint32_t s creenHeight,
251 const char* filename) {
252 // read back pixels
253 uint32_t readback[screenWidth * screenHeight];
254 GR_GL_CALL(gl, ReadPixels(0, // x
255 0, // y
256 screenWidth, // width
257 screenHeight, // height
258 GR_GL_RGBA, //format
259 GR_GL_UNSIGNED_BYTE, //type
260 readback));
261
262 // dump png
263 SkBitmap bm;
264 if (!bm.tryAllocPixels(SkImageInfo::MakeN32Premul(screenWidth, screenHeight) )) {
265 SkDebugf("couldn't allocate bitmap\n");
266 return;
267 }
268
269 bm.setPixels(readback);
270
271 if (!SkImageEncoder::EncodeFile(filename, bm, SkImageEncoder::kPNG_Type, 100 )) {
272 SkDebugf("------ failed to encode %s\n", filename);
273 remove(filename); // remove any partial file
274 return;
275 }
276 }
277 #endif
278
279 static void setup_framebuffer(const GrGLInterface* gl, int screenWidth, int scre enHeight) {
280 //Setup framebuffer
281 GrGLuint texture;
282 GR_GL_CALL(gl, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
283 GR_GL_CALL(gl, PixelStorei(GR_GL_PACK_ROW_LENGTH, 0));
284 GR_GL_CALL(gl, GenTextures(1, &texture));
285 GR_GL_CALL(gl, ActiveTexture(GR_GL_TEXTURE15));
286 GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, texture));
287 GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MAG_FILTER, GR_ GL_NEAREST));
288 GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MIN_FILTER, GR_ GL_NEAREST));
289 GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_WRAP_S, GR_GL_C LAMP_TO_EDGE));
290 GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_WRAP_T, GR_GL_C LAMP_TO_EDGE));
291 GR_GL_CALL(gl, TexImage2D(GR_GL_TEXTURE_2D,
292 0, //level
293 GR_GL_RGBA8, //internal format
294 screenWidth, // width
295 screenHeight, // height
296 0, //border
297 GR_GL_RGBA, //format
298 GR_GL_UNSIGNED_BYTE, // type
299 NULL));
300
301 // bind framebuffer
302 GrGLuint framebuffer;
303 GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, 0));
304 GR_GL_CALL(gl, GenFramebuffers(1, &framebuffer));
305 GR_GL_CALL(gl, BindFramebuffer(GR_GL_FRAMEBUFFER, framebuffer));
306 GR_GL_CALL(gl, FramebufferTexture2D(GR_GL_FRAMEBUFFER,
307 GR_GL_COLOR_ATTACHMENT0,
308 GR_GL_TEXTURE_2D,
309 texture, 0));
310 GR_GL_CALL(gl, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
311 GR_GL_CALL(gl, Viewport(0, 0, screenWidth, screenHeight));
312 }
313
314 //////////////////////////////////////////////////////////////////////////////// ///////////////////
315
316 void GLVertexAttributesBench::setup(const GrGLContext* ctx) {
317 const GrGLInterface* gl = ctx->interface();
318 setup_framebuffer(gl, kScreenWidth, kScreenHeight);
319
320 fProgram = compile_shader(ctx, fAttribs, kMaxAttribs);
321
322 // setup matrices
323 SkMatrix viewMatrices[kNumTri];
324 for (uint32_t i = 0 ; i < kNumTri; i++) {
325 SkMatrix m = SkMatrix::I();
326 m.setScale(0.0001f, 0.0001f);
327 viewMatrices[i] = m;
328 }
329
330 // setup VAO
331 GR_GL_CALL(gl, GenVertexArrays(1, &fVAO));
332 GR_GL_CALL(gl, BindVertexArray(fVAO));
333
334 // presetup vertex attributes, color is set to be a light gray no matter how many vertex
335 // attributes are used
336 float targetColor = 0.9f;
337 float colorContribution = targetColor / fAttribs;
338 fVertices.reset(static_cast<int>(kVerticesPerTri * kNumTri * fStride));
339 for (uint32_t i = 0; i < kNumTri; i++) {
340 unsigned char* ptr = &fVertices[static_cast<int>(i * kVerticesPerTri * f Stride)];
341 SkPoint* p = reinterpret_cast<SkPoint*>(ptr);
342 p->set(-1.0f, -1.0f); p++; p->set( 0.0f, 1.0f);
343 p = reinterpret_cast<SkPoint*>(ptr + fStride);
344 p->set( 1.0f, -1.0f); p++; p->set( 0.0f, 1.0f);
345 p = reinterpret_cast<SkPoint*>(ptr + fStride * 2);
346 p->set( 1.0f, 1.0f); p++; p->set( 0.0f, 1.0f);
347
348 SkPoint* position = reinterpret_cast<SkPoint*>(ptr);
349 viewMatrices[i].mapPointsWithStride(position, fStride, kVerticesPerTri);
350
351 // set colors
352 for (uint32_t j = 0; j < kVerticesPerTri; j++) {
353 GrGLfloat* f = reinterpret_cast<GrGLfloat*>(ptr + 2 * sizeof(SkPoint ) + fStride * j);
354 for (uint32_t k = 0; k < fAttribs * 4; k += 4) {
355 f[k] = colorContribution;
356 f[k + 1] = colorContribution;
357 f[k + 2] = colorContribution;
358 f[k + 3] = 1.0f;
359 }
360 }
361 }
362
363 GR_GL_CALL(gl, GenBuffers(1, &fVBO));
364 fBuffers.push_back(fVBO);
365
366 // clear screen
367 GR_GL_CALL(gl, ClearColor(0.03f, 0.03f, 0.03f, 1.0f));
368 GR_GL_CALL(gl, Clear(GR_GL_COLOR_BUFFER_BIT));
369
370 // set us up to draw
371 GR_GL_CALL(gl, UseProgram(fProgram));
372 GR_GL_CALL(gl, BindVertexArray(fVAO));
373 }
374
375 void GLVertexAttributesBench::onDraw(const int loops, SkCanvas* canvas) {
376 const GrGLContext* ctx = get_gl_context(canvas);
377 if (!ctx) {
378 return;
379 }
380
381 const GrGLInterface* gl = ctx->interface();
382
383 // upload vertex attributes
384 GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, fVBO));
385 GR_GL_CALL(gl, EnableVertexAttribArray(0));
386 GR_GL_CALL(gl, VertexAttribPointer(0, 4, GR_GL_FLOAT, GR_GL_FALSE, (GrGLsize i)fStride,
387 (GrGLvoid*)0));
388
389 size_t runningStride = 2 * sizeof(SkPoint);
390 for (uint32_t i = 0; i < fAttribs; i++) {
391 int attribId = i + 1;
392 GR_GL_CALL(gl, EnableVertexAttribArray(attribId));
393 GR_GL_CALL(gl, VertexAttribPointer(attribId, 4, GR_GL_FLOAT, GR_GL_FALSE ,
394 (GrGLsizei)fStride, (GrGLvoid*)(runni ngStride)));
395 runningStride += sizeof(GrGLfloat) * 4;
396 }
397
398 GR_GL_CALL(gl, BufferData(GR_GL_ARRAY_BUFFER, fVertices.count(), fVertices.b egin(),
399 GR_GL_STREAM_DRAW));
400
401 uint32_t maxTrianglesPerFlush = kNumTri;
402 uint32_t trianglesToDraw = loops * kDrawMultiplier;
403
404 while (trianglesToDraw > 0) {
405 uint32_t triangles = SkTMin(trianglesToDraw, maxTrianglesPerFlush);
406 GR_GL_CALL(gl, DrawArrays(GR_GL_TRIANGLES, 0, kVerticesPerTri * triangle s));
407 trianglesToDraw -= triangles;
408 }
409
410 #ifdef DUMP_IMAGES
411 //const char* filename = "/data/local/tmp/out.png";
412 SkString filename("out");
413 filename.appendf("_%s.png", this->getName());
414 dump_image(gl, kScreenWidth, kScreenHeight, filename.c_str());
415 #endif
416 }
417
418
419 ///////////////////////////////////////////////////////////////////////////////
420
421 DEF_BENCH( return new GLVertexAttributesBench(0) )
422 DEF_BENCH( return new GLVertexAttributesBench(1) )
423 DEF_BENCH( return new GLVertexAttributesBench(2) )
424 DEF_BENCH( return new GLVertexAttributesBench(3) )
425 DEF_BENCH( return new GLVertexAttributesBench(4) )
426 DEF_BENCH( return new GLVertexAttributesBench(5) )
427 DEF_BENCH( return new GLVertexAttributesBench(6) )
428 DEF_BENCH( return new GLVertexAttributesBench(7) )
429 #endif
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698