blob: ea0bbcb535ffd09deaee6e3f8551d3b27862a1f4 [file] [log] [blame]
joshualittf06c3892015-07-01 06:20:13 -07001/*
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"
joshualitt74a07db2015-07-01 12:39:07 -070011
joshualittf06c3892015-07-01 06:20:13 -070012#if SK_SUPPORT_GPU
joshualitt74a07db2015-07-01 12:39:07 -070013#include "GLBench.h"
Brian Salomon94efbf52016-11-29 13:43:05 -050014#include "GrShaderCaps.h"
Brian Salomon99938a82016-11-21 13:41:08 -050015#include "GrShaderVar.h"
egdanielf5294392015-10-21 07:14:17 -070016#include "gl/GrGLContext.h"
joshualittf06c3892015-07-01 06:20:13 -070017#include "gl/GrGLInterface.h"
joshualittf06c3892015-07-01 06:20:13 -070018#include "gl/GrGLUtil.h"
Brian Salomon94efbf52016-11-29 13:43:05 -050019#include "../private/GrGLSL.h"
joshualittf06c3892015-07-01 06:20:13 -070020#include <stdio.h>
21
22/*
23 * This is a native GL benchmark for determining the cost of uploading vertex attributes
24 */
joshualitt74a07db2015-07-01 12:39:07 -070025class GLVertexAttributesBench : public GLBench {
joshualittf06c3892015-07-01 06:20:13 -070026public:
27 GLVertexAttributesBench(uint32_t attribs)
28 : fTexture(0)
29 , fBuffers(0)
30 , fProgram(0)
joshualittf06c3892015-07-01 06:20:13 -070031 , fVBO(0)
32 , fAttribs(attribs)
33 , fStride(2 * sizeof(SkPoint) + fAttribs * sizeof(GrGLfloat) * 4) {
34 fName.appendf("GLVertexAttributesBench_%d", fAttribs);
35 }
36
37protected:
38 const char* onGetName() override { return fName.c_str(); }
joshualitt74a07db2015-07-01 12:39:07 -070039 void setup(const GrGLContext*) override;
mtkleina1ebeb22015-10-01 09:43:39 -070040 void glDraw(int loops, const GrGLContext*) override;
joshualitt74a07db2015-07-01 12:39:07 -070041 void teardown(const GrGLInterface*) override;
joshualittf06c3892015-07-01 06:20:13 -070042
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
50private:
joshualitt74a07db2015-07-01 12:39:07 -070051 GrGLuint setupShader(const GrGLContext*, uint32_t attribs, uint32_t maxAttribs);
52
joshualittf06c3892015-07-01 06:20:13 -070053 GrGLuint fTexture;
54 SkTArray<GrGLuint> fBuffers;
55 GrGLuint fProgram;
joshualittf06c3892015-07-01 06:20:13 -070056 GrGLuint fVBO;
57 SkTArray<unsigned char> fVertices;
58 uint32_t fAttribs;
59 size_t fStride;
60 SkString fName;
61 typedef Benchmark INHERITED;
62};
63
joshualittf06c3892015-07-01 06:20:13 -070064///////////////////////////////////////////////////////////////////////////////////////////////////
65
joshualitt74a07db2015-07-01 12:39:07 -070066GrGLuint GLVertexAttributesBench::setupShader(const GrGLContext* ctx, uint32_t attribs,
67 uint32_t maxAttribs) {
Brian Salomon1edc5b92016-11-29 13:43:46 -050068 const GrShaderCaps* shaderCaps = ctx->caps()->shaderCaps();
69 const char* version = shaderCaps->versionDeclString();
joshualittf06c3892015-07-01 06:20:13 -070070
71 // setup vertex shader
Ethan Nicholas8aa45692017-09-20 11:24:15 -040072 GrShaderVar aPosition("a_position", kFloat4_GrSLType, GrShaderVar::kIn_TypeModifier);
Brian Salomon99938a82016-11-21 13:41:08 -050073 SkTArray<GrShaderVar> aVars;
74 SkTArray<GrShaderVar> oVars;
joshualittf06c3892015-07-01 06:20:13 -070075
76 SkString vshaderTxt(version);
Brian Salomon1edc5b92016-11-29 13:43:46 -050077 aPosition.appendDecl(shaderCaps, &vshaderTxt);
joshualittf06c3892015-07-01 06:20:13 -070078 vshaderTxt.append(";\n");
79
80 for (uint32_t i = 0; i < attribs; i++) {
81 SkString aname;
82 aname.appendf("a_color_%d", i);
Brian Salomon99938a82016-11-21 13:41:08 -050083 aVars.push_back(GrShaderVar(aname.c_str(),
Ethan Nicholasf7b88202017-09-18 14:10:39 -040084 kHalf4_GrSLType,
Brian Salomon99938a82016-11-21 13:41:08 -050085 GrShaderVar::kIn_TypeModifier));
Brian Salomon1edc5b92016-11-29 13:43:46 -050086 aVars.back().appendDecl(shaderCaps, &vshaderTxt);
joshualittf06c3892015-07-01 06:20:13 -070087 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);
Brian Salomon99938a82016-11-21 13:41:08 -050094 oVars.push_back(GrShaderVar(oname.c_str(),
Ethan Nicholasf7b88202017-09-18 14:10:39 -040095 kHalf4_GrSLType,
Brian Salomon99938a82016-11-21 13:41:08 -050096 GrShaderVar::kOut_TypeModifier));
Brian Salomon1edc5b92016-11-29 13:43:46 -050097 oVars.back().appendDecl(shaderCaps, &vshaderTxt);
joshualittf06c3892015-07-01 06:20:13 -070098 vshaderTxt.append(";\n");
99 }
100
101 vshaderTxt.append(
102 "void main()\n"
103 "{\n"
Ethan Nicholasbed683a2017-09-26 14:23:59 -0400104 "sk_Position = a_position;\n");
joshualittf06c3892015-07-01 06:20:13 -0700105
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++) {
Ethan Nicholas8aa45692017-09-20 11:24:15 -0400112 vshaderTxt.appendf("%s = float4(0, 0, 0, 1);\n", oVars[i].c_str());
joshualittf06c3892015-07-01 06:20:13 -0700113 }
114
115 vshaderTxt.append("}\n");
116
joshualittf06c3892015-07-01 06:20:13 -0700117 // setup fragment shader
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400118 GrShaderVar oFragColor("o_FragColor", kHalf4_GrSLType, GrShaderVar::kOut_TypeModifier);
joshualittf06c3892015-07-01 06:20:13 -0700119 SkString fshaderTxt(version);
joshualittf06c3892015-07-01 06:20:13 -0700120
121 const char* fsOutName;
Brian Salomon1edc5b92016-11-29 13:43:46 -0500122 if (shaderCaps->mustDeclareFragmentShaderOutput()) {
123 oFragColor.appendDecl(shaderCaps, &fshaderTxt);
joshualittf06c3892015-07-01 06:20:13 -0700124 fshaderTxt.append(";\n");
125 fsOutName = oFragColor.c_str();
126 } else {
ethannicholas5961bc92016-10-12 06:39:56 -0700127 fsOutName = "sk_FragColor";
joshualittf06c3892015-07-01 06:20:13 -0700128 }
129
130 for (uint32_t i = 0; i < maxAttribs; i++) {
Brian Salomonf31ae492016-11-18 15:35:33 -0500131 oVars[i].setTypeModifier(GrShaderVar::kIn_TypeModifier);
Brian Salomon1edc5b92016-11-29 13:43:46 -0500132 oVars[i].appendDecl(shaderCaps, &fshaderTxt);
joshualittf06c3892015-07-01 06:20:13 -0700133 fshaderTxt.append(";\n");
134 }
135
136 fshaderTxt.appendf(
137 "void main()\n"
138 "{\n"
139 "%s = ", fsOutName);
140
141 fshaderTxt.appendf("%s", oVars[0].c_str());
142 for (uint32_t i = 1; i < maxAttribs; i++) {
143 fshaderTxt.appendf(" + %s", oVars[i].c_str());
144 }
145
146 fshaderTxt.append(";\n"
147 "}\n");
148
ethannicholas5961bc92016-10-12 06:39:56 -0700149 return CreateProgram(ctx, vshaderTxt.c_str(), fshaderTxt.c_str());
joshualittf06c3892015-07-01 06:20:13 -0700150}
151
152///////////////////////////////////////////////////////////////////////////////////////////////////
153
154void GLVertexAttributesBench::setup(const GrGLContext* ctx) {
155 const GrGLInterface* gl = ctx->interface();
joshualitt74a07db2015-07-01 12:39:07 -0700156 fTexture = SetupFramebuffer(gl, kScreenWidth, kScreenHeight);
joshualittf06c3892015-07-01 06:20:13 -0700157
joshualitt74a07db2015-07-01 12:39:07 -0700158 fProgram = setupShader(ctx, fAttribs, kMaxAttribs);
joshualittf06c3892015-07-01 06:20:13 -0700159
160 // setup matrices
161 SkMatrix viewMatrices[kNumTri];
162 for (uint32_t i = 0 ; i < kNumTri; i++) {
163 SkMatrix m = SkMatrix::I();
164 m.setScale(0.0001f, 0.0001f);
165 viewMatrices[i] = m;
166 }
167
joshualittf06c3892015-07-01 06:20:13 -0700168 // presetup vertex attributes, color is set to be a light gray no matter how many vertex
169 // attributes are used
170 float targetColor = 0.9f;
171 float colorContribution = targetColor / fAttribs;
172 fVertices.reset(static_cast<int>(kVerticesPerTri * kNumTri * fStride));
173 for (uint32_t i = 0; i < kNumTri; i++) {
174 unsigned char* ptr = &fVertices[static_cast<int>(i * kVerticesPerTri * fStride)];
175 SkPoint* p = reinterpret_cast<SkPoint*>(ptr);
176 p->set(-1.0f, -1.0f); p++; p->set( 0.0f, 1.0f);
177 p = reinterpret_cast<SkPoint*>(ptr + fStride);
178 p->set( 1.0f, -1.0f); p++; p->set( 0.0f, 1.0f);
179 p = reinterpret_cast<SkPoint*>(ptr + fStride * 2);
180 p->set( 1.0f, 1.0f); p++; p->set( 0.0f, 1.0f);
181
182 SkPoint* position = reinterpret_cast<SkPoint*>(ptr);
183 viewMatrices[i].mapPointsWithStride(position, fStride, kVerticesPerTri);
184
185 // set colors
186 for (uint32_t j = 0; j < kVerticesPerTri; j++) {
187 GrGLfloat* f = reinterpret_cast<GrGLfloat*>(ptr + 2 * sizeof(SkPoint) + fStride * j);
188 for (uint32_t k = 0; k < fAttribs * 4; k += 4) {
189 f[k] = colorContribution;
190 f[k + 1] = colorContribution;
191 f[k + 2] = colorContribution;
192 f[k + 3] = 1.0f;
193 }
194 }
195 }
196
197 GR_GL_CALL(gl, GenBuffers(1, &fVBO));
198 fBuffers.push_back(fVBO);
199
200 // clear screen
201 GR_GL_CALL(gl, ClearColor(0.03f, 0.03f, 0.03f, 1.0f));
202 GR_GL_CALL(gl, Clear(GR_GL_COLOR_BUFFER_BIT));
203
204 // set us up to draw
205 GR_GL_CALL(gl, UseProgram(fProgram));
joshualittf06c3892015-07-01 06:20:13 -0700206}
207
mtkleina1ebeb22015-10-01 09:43:39 -0700208void GLVertexAttributesBench::glDraw(int loops, const GrGLContext* ctx) {
joshualittf06c3892015-07-01 06:20:13 -0700209 const GrGLInterface* gl = ctx->interface();
210
211 // upload vertex attributes
212 GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, fVBO));
213 GR_GL_CALL(gl, EnableVertexAttribArray(0));
214 GR_GL_CALL(gl, VertexAttribPointer(0, 4, GR_GL_FLOAT, GR_GL_FALSE, (GrGLsizei)fStride,
215 (GrGLvoid*)0));
216
217 size_t runningStride = 2 * sizeof(SkPoint);
218 for (uint32_t i = 0; i < fAttribs; i++) {
219 int attribId = i + 1;
220 GR_GL_CALL(gl, EnableVertexAttribArray(attribId));
221 GR_GL_CALL(gl, VertexAttribPointer(attribId, 4, GR_GL_FLOAT, GR_GL_FALSE,
222 (GrGLsizei)fStride, (GrGLvoid*)(runningStride)));
223 runningStride += sizeof(GrGLfloat) * 4;
224 }
225
226 GR_GL_CALL(gl, BufferData(GR_GL_ARRAY_BUFFER, fVertices.count(), fVertices.begin(),
227 GR_GL_STREAM_DRAW));
228
229 uint32_t maxTrianglesPerFlush = kNumTri;
230 uint32_t trianglesToDraw = loops * kDrawMultiplier;
231
232 while (trianglesToDraw > 0) {
233 uint32_t triangles = SkTMin(trianglesToDraw, maxTrianglesPerFlush);
234 GR_GL_CALL(gl, DrawArrays(GR_GL_TRIANGLES, 0, kVerticesPerTri * triangles));
235 trianglesToDraw -= triangles;
236 }
237
joshualitt74a07db2015-07-01 12:39:07 -0700238#if 0
joshualittf06c3892015-07-01 06:20:13 -0700239 //const char* filename = "/data/local/tmp/out.png";
240 SkString filename("out");
241 filename.appendf("_%s.png", this->getName());
joshualitt74a07db2015-07-01 12:39:07 -0700242 DumpImage(gl, kScreenWidth, kScreenHeight, filename.c_str());
joshualittf06c3892015-07-01 06:20:13 -0700243#endif
244}
245
joshualitt74a07db2015-07-01 12:39:07 -0700246void GLVertexAttributesBench::teardown(const GrGLInterface* gl) {
247 // teardown
248 GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, 0));
249 GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, 0));
250 GR_GL_CALL(gl, BindFramebuffer(GR_GL_FRAMEBUFFER, 0));
251 GR_GL_CALL(gl, DeleteTextures(1, &fTexture));
252 GR_GL_CALL(gl, DeleteProgram(fProgram));
253 GR_GL_CALL(gl, DeleteBuffers(fBuffers.count(), fBuffers.begin()));
joshualitt31b21f62015-07-16 13:40:51 -0700254 fBuffers.reset();
joshualitt74a07db2015-07-01 12:39:07 -0700255}
joshualittf06c3892015-07-01 06:20:13 -0700256
257///////////////////////////////////////////////////////////////////////////////
258
259DEF_BENCH( return new GLVertexAttributesBench(0) )
260DEF_BENCH( return new GLVertexAttributesBench(1) )
261DEF_BENCH( return new GLVertexAttributesBench(2) )
262DEF_BENCH( return new GLVertexAttributesBench(3) )
263DEF_BENCH( return new GLVertexAttributesBench(4) )
264DEF_BENCH( return new GLVertexAttributesBench(5) )
265DEF_BENCH( return new GLVertexAttributesBench(6) )
266DEF_BENCH( return new GLVertexAttributesBench(7) )
267#endif