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

Side by Side Diff: src/gpu/instanced/GLInstancedRendering.cpp

Issue 2066993003: Begin instanced rendering for simple shapes (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 4 years, 6 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 | « src/gpu/instanced/GLInstancedRendering.h ('k') | src/gpu/instanced/InstanceProcessor.h » ('j') | 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 2016 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 "GLInstancedRendering.h"
9
10 #include "GrResourceProvider.h"
11 #include "gl/GrGLGpu.h"
12 #include "instanced/InstanceProcessor.h"
13
14 #define GL_CALL(X) GR_GL_CALL(this->glGpu()->glInterface(), X)
15
16 namespace gr_instanced {
17
18 class GLInstancedRendering::GLBatch : public InstancedRendering::Batch {
19 public:
20 DEFINE_BATCH_CLASS_ID
21
22 GLBatch(GLInstancedRendering* instRendering, int instanceIdx)
23 : INHERITED(ClassID(), instRendering, instanceIdx) {
24 }
25
26 private:
27 int fEmulatedBaseInstance;
28 int fGLDrawCmdsIdx;
29 int fNumGLDrawCmds;
30
31 friend class GLInstancedRendering;
32
33 typedef Batch INHERITED;
34 };
35
36 GLInstancedRendering* GLInstancedRendering::CreateIfSupported(GrGLGpu* gpu) {
37 const GrGLCaps& caps = gpu->glCaps();
38 AntialiasMode lastSupportedAAMode;
39 if (!caps.vertexArrayObjectSupport() ||
40 !caps.drawIndirectSupport() ||
41 !InstanceProcessor::IsSupported(*caps.glslCaps(), caps, &lastSupportedAA Mode)) {
42 return nullptr;
43 }
44 return new GLInstancedRendering(gpu, lastSupportedAAMode);
45 }
46
47 GLInstancedRendering::GLInstancedRendering(GrGLGpu* gpu, AntialiasMode lastSuppo rtedAAMode)
48 : INHERITED(gpu, lastSupportedAAMode),
49 fVertexArrayID(0),
50 fGLDrawCmdsInfo(0),
51 fInstanceAttribsBufferUniqueId(SK_InvalidUniqueID) {
52 }
53
54 GLInstancedRendering::~GLInstancedRendering() {
55 if (fVertexArrayID) {
56 GL_CALL(DeleteVertexArrays(1, &fVertexArrayID));
57 this->glGpu()->notifyVertexArrayDelete(fVertexArrayID);
58 }
59 }
60
61 inline GrGLGpu* GLInstancedRendering::glGpu() const {
62 return static_cast<GrGLGpu*>(this->gpu());
63 }
64
65 InstancedRendering::Batch* GLInstancedRendering::createBatch(int instanceIdx) {
66 return new GLBatch(this, instanceIdx);
67 }
68
69 void GLInstancedRendering::onBeginFlush(GrResourceProvider* rp) {
70 // Count what there is to draw.
71 BatchList::Iter iter;
72 iter.init(this->batchList(), BatchList::Iter::kHead_IterStart);
73 int numGLInstances = 0;
74 int numGLDrawCmds = 0;
75 while (Batch* b = iter.get()) {
76 GLBatch* batch = static_cast<GLBatch*>(b);
77 iter.next();
78
79 const auto& drawCmds = batch->fDrawCmds;
80 for (int c = 0; c < drawCmds.count(); ++c) {
81 numGLInstances += drawCmds[c].fInstanceRange.fCount;
82 if (c > 0 && drawCmds[c].fGeometry == drawCmds[c - 1].fGeometry) {
83 // When two adjacent draw commands have the same geometry, we wi ll rearrange the
84 // instances for the GL buffer and combine them into a single co mmand.
85 continue;
86 }
87 ++numGLDrawCmds;
88 }
89 }
90 if (!numGLDrawCmds) {
91 return;
92 }
93 SkASSERT(numGLInstances);
94
95 // Lazily create a vertex array object.
96 if (!fVertexArrayID) {
97 GL_CALL(GenVertexArrays(1, &fVertexArrayID));
98 if (!fVertexArrayID) {
99 return;
100 }
101 this->glGpu()->bindVertexArray(fVertexArrayID);
102
103 // Attach our index buffer to the vertex array.
104 GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER,
105 static_cast<const GrGLBuffer*>(this->indexBuffer())-> bufferID()));
106
107 // Set up the non-instanced attribs.
108 this->glGpu()->bindBuffer(kVertex_GrBufferType,
109 static_cast<const GrGLBuffer*>(this->vertexBuf fer()));
110 GL_CALL(EnableVertexAttribArray((int)Attrib::kShapeCoords));
111 GL_CALL(VertexAttribPointer((int)Attrib::kShapeCoords, 2, GR_GL_FLOAT, G R_GL_FALSE,
112 sizeof(ShapeVertex), (void*) offsetof(ShapeV ertex, fX)));
113 GL_CALL(EnableVertexAttribArray((int)Attrib::kVertexAttrs));
114 GL_CALL(VertexAttribIPointer((int)Attrib::kVertexAttrs, 1, GR_GL_INT, si zeof(ShapeVertex),
115 (void*) offsetof(ShapeVertex, fAttrs)));
116
117 SkASSERT(SK_InvalidUniqueID == fInstanceAttribsBufferUniqueId);
118 }
119
120 // Create and map instance and draw-indirect buffers.
121 SkASSERT(!fInstanceBuffer);
122 fInstanceBuffer.reset(static_cast<GrGLBuffer*>(
123 rp->createBuffer(sizeof(Instance) * numGLInstances, kVertex_GrBufferType ,
124 kDynamic_GrAccessPattern, GrResourceProvider::kNoPendin gIO_Flag)));
125 if (!fInstanceBuffer) {
126 return;
127 }
128
129 SkASSERT(!fDrawIndirectBuffer);
130 fDrawIndirectBuffer.reset(static_cast<GrGLBuffer*>(
131 rp->createBuffer(sizeof(GrGLDrawElementsIndirectCommand) * numGLDrawCmds ,
132 kDrawIndirect_GrBufferType, kDynamic_GrAccessPattern,
133 GrResourceProvider::kNoPendingIO_Flag)));
134 if (!fDrawIndirectBuffer) {
135 return;
136 }
137
138 Instance* glMappedInstances = static_cast<Instance*>(fInstanceBuffer->map()) ;
139 int glInstancesIdx = 0;
140
141 auto* glMappedCmds = static_cast<GrGLDrawElementsIndirectCommand*>(fDrawIndi rectBuffer->map());
142 int glDrawCmdsIdx = 0;
143
144 bool baseInstanceSupport = this->glGpu()->glCaps().baseInstanceSupport();
145
146 if (!baseInstanceSupport) {
147 fGLDrawCmdsInfo.reset(numGLDrawCmds);
148 }
149
150 // Generate the instance and draw-indirect buffer contents based on the batc hes in existence.
151 iter.init(this->batchList(), BatchList::Iter::kHead_IterStart);
152 while (Batch* b = iter.get()) {
153 GLBatch* batch = static_cast<GLBatch*>(b);
154 iter.next();
155
156 batch->fEmulatedBaseInstance = baseInstanceSupport ? 0 : glInstancesIdx;
157 batch->fGLDrawCmdsIdx = glDrawCmdsIdx;
158 batch->fNumGLDrawCmds = 0;
159
160 const auto& drawCmds = batch->fDrawCmds;
161 int cidx = 0;
162 SkASSERT(!drawCmds.empty());
163 do {
164 IndexRange geometry = drawCmds[cidx].fGeometry;
165 int instanceCount = 0;
166
167 do {
168 SkASSERT(drawCmds[cidx].isValid());
169 InstanceRange range = drawCmds[cidx].fInstanceRange;
170 memcpy(&glMappedInstances[glInstancesIdx + instanceCount],
171 &this->instance(range.fStart), range.fCount * sizeof(Inst ance));
172 instanceCount += range.fCount;
173 } while (++cidx < drawCmds.count() && drawCmds[cidx].fGeometry == ge ometry);
174
175 GrGLDrawElementsIndirectCommand& glCmd = glMappedCmds[glDrawCmdsIdx] ;
176 glCmd.fCount = geometry.fCount;
177 glCmd.fInstanceCount = instanceCount;
178 glCmd.fFirstIndex = geometry.fStart;
179 glCmd.fBaseVertex = 0;
180 glCmd.fBaseInstance = baseInstanceSupport ? glInstancesIdx : 0;
181
182 if (!baseInstanceSupport) {
183 fGLDrawCmdsInfo[glDrawCmdsIdx].fInstanceCount = instanceCount;
184 }
185
186 glInstancesIdx += instanceCount;
187 ++glDrawCmdsIdx;
188 ++batch->fNumGLDrawCmds;
189 } while (cidx < drawCmds.count());
190 }
191
192 SkASSERT(glDrawCmdsIdx == numGLDrawCmds);
193 fDrawIndirectBuffer->unmap();
194
195 SkASSERT(glInstancesIdx == numGLInstances);
196 fInstanceBuffer->unmap();
197 }
198
199 void GLInstancedRendering::onDraw(const GrPipeline& pipeline, const InstanceProc essor& instProc,
200 const Batch* baseBatch) {
201 if (!fDrawIndirectBuffer) {
202 return; // beginFlush was not successful.
203 }
204 if (!this->glGpu()->flushGLState(pipeline, instProc)) {
205 return;
206 }
207
208 this->glGpu()->bindBuffer(kDrawIndirect_GrBufferType, fDrawIndirectBuffer.ge t());
209
210 const GrGLCaps& glCaps = this->glGpu()->glCaps();
211 const GLBatch* batch = static_cast<const GLBatch*>(baseBatch);
212 int numCommands = batch->fNumGLDrawCmds;
213
214 SkASSERT(SkToBool(fGLDrawCmdsInfo) == !glCaps.baseInstanceSupport());
215
216 #if 0
217 SkDebugf("Instanced batch: [");
218 for (int i = 0; i < numCommands; ++i) {
219 SkDebugf("%s%i * %s", (i ? ", " : ""), batch->fDrawCmds[i].fInstanceRa nge.fCount,
220 InstanceProcessor::GetNameOfIndexRange(batch->fDrawCmds[i].fGeo metry));
221 }
222 SkDebugf("]\n");
223 #endif
224
225 if (1 == numCommands || !glCaps.baseInstanceSupport() || !glCaps.multiDrawIn directSupport()) {
226 int emulatedBaseInstance = batch->fEmulatedBaseInstance;
227 for (int i = 0; i < numCommands; ++i) {
228 int glCmdIdx = batch->fGLDrawCmdsIdx + i;
229 this->flushInstanceAttribs(emulatedBaseInstance);
230 GL_CALL(DrawElementsIndirect(GR_GL_TRIANGLES, GR_GL_UNSIGNED_BYTE,
231 (GrGLDrawElementsIndirectCommand*) null ptr + glCmdIdx));
232 if (!glCaps.baseInstanceSupport()) {
233 emulatedBaseInstance += fGLDrawCmdsInfo[glCmdIdx].fInstanceCount ;
234 }
235 }
236 } else {
237 int glCmdsIdx = batch->fGLDrawCmdsIdx;
238 this->flushInstanceAttribs(batch->fEmulatedBaseInstance);
239 GL_CALL(MultiDrawElementsIndirect(GR_GL_TRIANGLES, GR_GL_UNSIGNED_BYTE,
240 (GrGLDrawElementsIndirectCommand*) nul lptr + glCmdsIdx,
241 numCommands, 0));
242 }
243 }
244
245 void GLInstancedRendering::flushInstanceAttribs(int baseInstance) {
246 SkASSERT(fVertexArrayID);
247 this->glGpu()->bindVertexArray(fVertexArrayID);
248
249 SkASSERT(fInstanceBuffer);
250 if (fInstanceAttribsBufferUniqueId != fInstanceBuffer->getUniqueID() ||
251 fInstanceAttribsBaseInstance != baseInstance) {
252 Instance* offsetInBuffer = (Instance*) nullptr + baseInstance;
253
254 this->glGpu()->bindBuffer(kVertex_GrBufferType, fInstanceBuffer.get());
255
256 // Info attrib.
257 GL_CALL(EnableVertexAttribArray((int)Attrib::kInstanceInfo));
258 GL_CALL(VertexAttribIPointer((int)Attrib::kInstanceInfo, 1, GR_GL_UNSIGN ED_INT,
259 sizeof(Instance), &offsetInBuffer->fInfo));
260 GL_CALL(VertexAttribDivisor((int)Attrib::kInstanceInfo, 1));
261
262 // Shape matrix attrib.
263 GL_CALL(EnableVertexAttribArray((int)Attrib::kShapeMatrixX));
264 GL_CALL(EnableVertexAttribArray((int)Attrib::kShapeMatrixY));
265 GL_CALL(VertexAttribPointer((int)Attrib::kShapeMatrixX, 3, GR_GL_FLOAT, GR_GL_FALSE,
266 sizeof(Instance), &offsetInBuffer->fShapeMat rix2x3[0]));
267 GL_CALL(VertexAttribPointer((int)Attrib::kShapeMatrixY, 3, GR_GL_FLOAT, GR_GL_FALSE,
268 sizeof(Instance), &offsetInBuffer->fShapeMat rix2x3[3]));
269 GL_CALL(VertexAttribDivisor((int)Attrib::kShapeMatrixX, 1));
270 GL_CALL(VertexAttribDivisor((int)Attrib::kShapeMatrixY, 1));
271
272 // Color attrib.
273 GL_CALL(EnableVertexAttribArray((int)Attrib::kColor));
274 GL_CALL(VertexAttribPointer((int)Attrib::kColor, 4, GR_GL_UNSIGNED_BYTE, GR_GL_TRUE,
275 sizeof(Instance), &offsetInBuffer->fColor));
276 GL_CALL(VertexAttribDivisor((int)Attrib::kColor, 1));
277
278 // Local rect attrib.
279 GL_CALL(EnableVertexAttribArray((int)Attrib::kLocalRect));
280 GL_CALL(VertexAttribPointer((int)Attrib::kLocalRect, 4, GR_GL_FLOAT, GR_ GL_FALSE,
281 sizeof(Instance), &offsetInBuffer->fLocalRec t));
282 GL_CALL(VertexAttribDivisor((int)Attrib::kLocalRect, 1));
283
284 fInstanceAttribsBufferUniqueId = fInstanceBuffer->getUniqueID();
285 fInstanceAttribsBaseInstance = baseInstance;
286 }
287 }
288
289 void GLInstancedRendering::onEndFlush() {
290 fInstanceBuffer.reset();
291 fDrawIndirectBuffer.reset();
292 fGLDrawCmdsInfo.reset(0);
293 }
294
295 void GLInstancedRendering::onResetGpuResources(ResetType resetType) {
296 if (fVertexArrayID && ResetType::kDestroy == resetType) {
297 GL_CALL(DeleteVertexArrays(1, &fVertexArrayID));
298 this->glGpu()->notifyVertexArrayDelete(fVertexArrayID);
299 }
300 fVertexArrayID = 0;
301 fInstanceBuffer.reset();
302 fDrawIndirectBuffer.reset();
303 fInstanceAttribsBufferUniqueId = SK_InvalidUniqueID;
304 }
305
306 }
OLDNEW
« no previous file with comments | « src/gpu/instanced/GLInstancedRendering.h ('k') | src/gpu/instanced/InstanceProcessor.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698