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

Side by Side Diff: bench/GLVec4ScalarBench.cpp

Issue 1225383002: Added a GLBench for testing performance of vec4 vs scalar for coverage in generated shaders. (Closed) Base URL: https://skia.googlesource.com/skia@master
Patch Set: 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 "SkMatrix.h"
9 #include "SkPoint.h"
10 #include "SkString.h"
11
12 #if SK_SUPPORT_GPU
13 #include "GLBench.h"
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
20 #include <stdio.h>
21
22 /**
23 * This is a GL benchmark for comparing the performance of using vec4 or float f or coverage in GLSL.
24 * The generated shader code from this bench will draw several overlapping circl es, one in each
25 * stage, to simulate coverage calculations. The number of circles (i.e. the nu mber of stages) can
26 * be set as a parameter.
27 */
28
29 class GLVec4ScalarBench : public GLBench {
30 public:
31 /*
32 * Use float or vec4 as GLSL data type for the output coverage
33 */
34 enum CoverageSetup {
35 kUseScalar_CoverageSetup,
36 kUseVec4_CoverageSetup,
37 };
38
39 /*
40 * numStages determines the number of shader stages before the XP,
41 * which consequently determines how many circles are drawn
42 */
43 GLVec4ScalarBench(CoverageSetup coverageSetup, uint32_t numStages)
44 : fCoverageSetup(coverageSetup)
45 , fNumStages(numStages)
46 , fVboId(0)
47 , fProgram(0)
48 , fVaoId(0) {
49 fName = NumStagesSetupToStr(coverageSetup, numStages);
50 }
51
52 protected:
53 const char* onGetName() override {
54 return fName.c_str();
55 }
56
57 void setup(const GrGLContext*) override;
58 void glDraw(const int loops, const GrGLContext*) override;
59 void teardown(const GrGLInterface*) override;
60
61 private:
62 void setupSingleVbo(const GrGLInterface*, const SkMatrix*);
63 GrGLuint setupShader(const GrGLContext*);
64
65
66 static SkString NumStagesSetupToStr(CoverageSetup coverageSetup, uint32_t nu mStages) {
67 SkString name("GLVec4ScalarBench");
68 switch (coverageSetup) {
69 default:
70 case kUseScalar_CoverageSetup:
71 name.appendf("_scalar_%u_stage", numStages);
72 break;
73 case kUseVec4_CoverageSetup:
74 name.appendf("_vec4_%u_stage", numStages);
75 break;
76 }
77 return name;
78 }
79
80 static const GrGLuint kScreenWidth = 800;
81 static const GrGLuint kScreenHeight = 600;
82 static const uint32_t kNumTriPerDraw = 512;
83 static const uint32_t kVerticesPerTri = 3;
84
85 SkString fName;
86 CoverageSetup fCoverageSetup;
87 uint32_t fNumStages;
88 GrGLuint fVboId;
89 GrGLuint fProgram;
90 GrGLuint fVaoId;
91 GrGLuint fFboTextureId;
92 };
93
94 //////////////////////////////////////////////////////////////////////////////// ///////////////////
95
96 GrGLuint GLVec4ScalarBench::setupShader(const GrGLContext* ctx) {
97 const char* version = GrGLGetGLSLVersionDecl(*ctx);
98
99 // this shader draws fNumStages overlapping circles of increasing opacity (c overage) and
100 // decreasing size, with the center of each subsequent circle closer to the bottom-right
101 // corner of the screen than the previous circle.
102
103 // set up vertex shader; this is a trivial vertex shader that passes through position and color
104 GrGLShaderVar aPosition("a_position", kVec2f_GrSLType, GrShaderVar::kAttribu te_TypeModifier);
105 GrGLShaderVar oPosition("o_position", kVec2f_GrSLType, GrShaderVar::kVarying Out_TypeModifier);
106 GrGLShaderVar aColor("a_color", kVec3f_GrSLType, GrShaderVar::kAttribute_Typ eModifier);
107 GrGLShaderVar oColor("o_color", kVec3f_GrSLType, GrShaderVar::kVaryingOut_Ty peModifier);
108
109 SkString vshaderTxt(version);
110 aPosition.appendDecl(*ctx, &vshaderTxt);
111 vshaderTxt.append(";\n");
112 aColor.appendDecl(*ctx, &vshaderTxt);
113 vshaderTxt.append(";\n");
114 oPosition.appendDecl(*ctx, &vshaderTxt);
115 vshaderTxt.append(";\n");
116 oColor.appendDecl(*ctx, &vshaderTxt);
117 vshaderTxt.append(";\n");
118
119 vshaderTxt.append(
120 "void main()\n"
121 "{\n"
122 " gl_Position = vec4(a_position, 0.f, 1.f);\n"
123 " o_position = a_position;\n"
124 " o_color = a_color;\n"
125 "}\n");
126
127 const GrGLInterface* gl = ctx->interface();
128
129 // set up fragment shader; this fragment shader will have fNumStages coverag e stages plus an
130 // XP stage at the end. Each coverage stage computes the pixel's distance f rom some hard-
131 // coded center and compare that to some hard-coded circle radius to compute a coverage.
132 // Then, this coverage is mixed with the coverage from the previous stage an d passed to the
133 // next stage.
134 GrGLShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_T ypeModifier);
135 SkString fshaderTxt(version);
136 GrGLAppendGLSLDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, gl->f Standard,
137 &fshaderTxt);
138 oPosition.setTypeModifier(GrShaderVar::kVaryingIn_TypeModifier);
139 oPosition.appendDecl(*ctx, &fshaderTxt);
140 fshaderTxt.append(";\n");
141 oColor.setTypeModifier(GrShaderVar::kVaryingIn_TypeModifier);
142 oColor.appendDecl(*ctx, &fshaderTxt);
143 fshaderTxt.append(";\n");
144
145 const char* fsOutName;
146 if (ctx->caps()->glslCaps()->mustDeclareFragmentShaderOutput()) {
147 oFragColor.appendDecl(*ctx, &fshaderTxt);
148 fshaderTxt.append(";\n");
149 fsOutName = oFragColor.c_str();
150 } else {
151 fsOutName = "gl_FragColor";
152 }
153
154 switch (fCoverageSetup) {
tomhudson 2015/07/13 16:00:13 These two cases are identical *except for* two poi
155 default:
156 case kUseVec4_CoverageSetup:
157 fshaderTxt.appendf(
158 "void main()\n"
159 "{\n"
160 " vec4 outputColor;\n"
161 " vec4 outputCoverage;\n"
162 " outputColor = vec4(%s, 1.0);\n"
163 " outputCoverage = vec4(1.0);\n",
164 oColor.getName().c_str());
165 break;
166 case kUseScalar_CoverageSetup:
167 fshaderTxt.appendf(
168 "void main()\n"
169 "{\n"
170 " vec4 outputColor;\n"
171 " float outputCoverage;\n"
172 " outputColor = vec4(%s, 1.0);\n"
173 " outputCoverage = 1.0;\n",
174 oColor.getName().c_str());
175 break;
176 }
177 float radius = 1.0f;
178 for (uint32_t i = 0; i < fNumStages; i++) {
179 float centerX = 1.0f - radius;
180 float centerY = 1.0f - radius;
181 switch (fCoverageSetup) {
tomhudson 2015/07/13 16:00:13 As above, can we merge most of the text of these t
182 default:
183 case kUseVec4_CoverageSetup:
184 fshaderTxt.appendf(
185 " {\n"
186 " float d = length(%s - vec2(%f, %f));\n"
187 " float edgeAlpha = clamp(100.0 * (%f - d), 0.0, 1.0);\n"
188 " outputCoverage = 0.5 * outputCoverage + 0.5 * v ec4(edgeAlpha);\n"
189 " }\n",
190 oPosition.getName().c_str(),
191 centerX, centerY,
192 radius
193 );
194 break;
195 case kUseScalar_CoverageSetup:
196 fshaderTxt.appendf(
197 " {\n"
198 " float d = length(%s - vec2(%f, %f));\n"
199 " float edgeAlpha = clamp(100.0 * (%f - d), 0.0, 1.0);\n"
200 " outputCoverage = 0.5 * outputCoverage + 0.5 * e dgeAlpha;\n"
201 " }\n",
202 oPosition.getName().c_str(),
203 centerX, centerY,
204 radius
205 );
206 break;
207 }
208 radius *= 0.8f;
209 }
210 fshaderTxt.appendf(
211 " {\n"
212 " %s = outputColor * outputCoverage;\n"
213 " }\n"
214 "}\n",
215 fsOutName);
216
217 return CreateProgram(gl, vshaderTxt.c_str(), fshaderTxt.c_str());
218 }
219
220 template<typename Func>
221 static void setup_matrices(int numQuads, Func f) {
222 // We draw a really small triangle so we are not fill rate limited
223 for (int i = 0 ; i < numQuads; i++) {
224 SkMatrix m = SkMatrix::I();
225 m.setScale(0.01f, 0.01f);
226 f(m);
227 }
228 }
229
230 //////////////////////////////////////////////////////////////////////////////// ///////////////////
231
232 struct Vertex {
233 SkPoint fPositions;
234 GrGLfloat fColors[3];
235 };
236
237 void GLVec4ScalarBench::setupSingleVbo(const GrGLInterface* gl, const SkMatrix* viewMatrices) {
238 // triangles drawn will alternate between the top-right half of the screen a nd the bottom-left
239 // half of the screen
240 Vertex vertices[kVerticesPerTri * kNumTriPerDraw];
241 for (uint32_t i = 0; i < kNumTriPerDraw; i++) {
242 Vertex* v = &vertices[i * kVerticesPerTri];
243 if (i % 2 == 0) {
244 v[0].fPositions.set(-1.0f, -1.0f);
245 v[1].fPositions.set( 1.0f, -1.0f);
246 v[2].fPositions.set( 1.0f, 1.0f);
247 } else {
248 v[0].fPositions.set(-1.0f, -1.0f);
249 v[1].fPositions.set( 1.0f, 1.0f);
250 v[2].fPositions.set( -1.0f, 1.0f);
251 }
252 SkPoint* position = reinterpret_cast<SkPoint*>(v);
253 viewMatrices[i].mapPointsWithStride(position, sizeof(Vertex), kVerticesP erTri);
254
255 GrGLfloat color[3] = {1.0f, 0.0f, 1.0f};
256 for (uint32_t j = 0; j < kVerticesPerTri; j++) {
257 v->fColors[0] = color[0];
258 v->fColors[1] = color[1];
259 v->fColors[2] = color[2];
260 v++;
261 }
262 }
263
264 GR_GL_CALL(gl, GenBuffers(1, &fVboId));
265 GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, fVboId));
266 GR_GL_CALL(gl, EnableVertexAttribArray(0));
267 GR_GL_CALL(gl, EnableVertexAttribArray(1));
268 GR_GL_CALL(gl, VertexAttribPointer(0, 2, GR_GL_FLOAT, GR_GL_FALSE, sizeof(Ve rtex),
269 (GrGLvoid*)0));
270 GR_GL_CALL(gl, VertexAttribPointer(1, 3, GR_GL_FLOAT, GR_GL_FALSE, sizeof(Ve rtex),
271 (GrGLvoid*)(sizeof(SkPoint))));
272 GR_GL_CALL(gl, BufferData(GR_GL_ARRAY_BUFFER, sizeof(vertices), vertices, GR _GL_STATIC_DRAW));
273 }
274
275 void GLVec4ScalarBench::setup(const GrGLContext* ctx) {
276 const GrGLInterface* gl = ctx->interface();
277 fFboTextureId = SetupFramebuffer(gl, kScreenWidth, kScreenHeight);
278
279 fProgram = this->setupShader(ctx);
280
281 GR_GL_CALL(gl, GenVertexArrays(1, &fVaoId));
282 GR_GL_CALL(gl, BindVertexArray(fVaoId));
283
284 int index = 0;
285 SkMatrix viewMatrices[kNumTriPerDraw];
286 setup_matrices(kNumTriPerDraw, [&index, &viewMatrices](const SkMatrix& m) {
287 viewMatrices[index++] = m;
288 });
289 this->setupSingleVbo(gl, viewMatrices);
290
291 GR_GL_CALL(gl, UseProgram(fProgram));
292 GR_GL_CALL(gl, BindVertexArray(fVaoId));
293 }
294
295 void GLVec4ScalarBench::glDraw(const int loops, const GrGLContext* ctx) {
296 const GrGLInterface* gl = ctx->interface();
297
298 for (int i = 0; i < loops; i++) {
299 GR_GL_CALL(gl, DrawArrays(GR_GL_TRIANGLES, 0, kVerticesPerTri * kNumTriP erDraw));
300 }
301
302
303 #if 0
304 SkString filename("out");
305 filename.appendf("_%s.png", this->getName());
306 DumpImage(gl, kScreenWidth, kScreenHeight, filename.c_str());
307 #endif
308 }
309
310 void GLVec4ScalarBench::teardown(const GrGLInterface* gl) {
311 GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, 0));
312 GR_GL_CALL(gl, BindVertexArray(0));
313 GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, 0));
314 GR_GL_CALL(gl, BindFramebuffer(GR_GL_FRAMEBUFFER, 0));
315 GR_GL_CALL(gl, DeleteTextures(1, &fFboTextureId));
316 GR_GL_CALL(gl, DeleteProgram(fProgram));
317 GR_GL_CALL(gl, DeleteBuffers(1, &fVboId));
318 GR_GL_CALL(gl, DeleteVertexArrays(1, &fVaoId));
319 }
320
321 ///////////////////////////////////////////////////////////////////////////////
322
323 DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseScalar_CoverageSe tup, 1) )
324 DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseVec4_CoverageSetu p, 1) )
325 DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseScalar_CoverageSe tup, 2) )
326 DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseVec4_CoverageSetu p, 2) )
327 DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseScalar_CoverageSe tup, 4) )
328 DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseVec4_CoverageSetu p, 4) )
329 DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseScalar_CoverageSe tup, 6) )
330 DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseVec4_CoverageSetu p, 6) )
331 DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseScalar_CoverageSe tup, 8) )
332 DEF_BENCH( return new GLVec4ScalarBench(GLVec4ScalarBench::kUseVec4_CoverageSetu p, 8) )
333
334 #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