OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GLInstancedRendering.h" | 8 #include "GLInstancedRendering.h" |
9 | 9 |
10 #include "GrResourceProvider.h" | 10 #include "GrResourceProvider.h" |
(...skipping 16 matching lines...) Expand all Loading... |
27 int fGLDrawCmdsIdx; | 27 int fGLDrawCmdsIdx; |
28 | 28 |
29 friend class GLInstancedRendering; | 29 friend class GLInstancedRendering; |
30 | 30 |
31 typedef Batch INHERITED; | 31 typedef Batch INHERITED; |
32 }; | 32 }; |
33 | 33 |
34 GrCaps::InstancedSupport GLInstancedRendering::CheckSupport(const GrGLCaps& glCa
ps) { | 34 GrCaps::InstancedSupport GLInstancedRendering::CheckSupport(const GrGLCaps& glCa
ps) { |
35 // This method is only intended to be used for initializing fInstancedSuppor
t in the caps. | 35 // This method is only intended to be used for initializing fInstancedSuppor
t in the caps. |
36 SkASSERT(GrCaps::InstancedSupport::kNone == glCaps.instancedSupport()); | 36 SkASSERT(GrCaps::InstancedSupport::kNone == glCaps.instancedSupport()); |
37 if (!glCaps.vertexArrayObjectSupport() || !glCaps.drawIndirectSupport()) { | 37 if (!glCaps.vertexArrayObjectSupport() || |
| 38 (!glCaps.drawIndirectSupport() && !glCaps.drawInstancedSupport())) { |
38 return GrCaps::InstancedSupport::kNone; | 39 return GrCaps::InstancedSupport::kNone; |
39 } | 40 } |
40 return InstanceProcessor::CheckSupport(*glCaps.glslCaps(), glCaps); | 41 return InstanceProcessor::CheckSupport(*glCaps.glslCaps(), glCaps); |
41 } | 42 } |
42 | 43 |
43 GLInstancedRendering::GLInstancedRendering(GrGLGpu* gpu) | 44 GLInstancedRendering::GLInstancedRendering(GrGLGpu* gpu) |
44 : INHERITED(gpu), | 45 : INHERITED(gpu), |
45 fVertexArrayID(0), | 46 fVertexArrayID(0), |
46 fGLDrawCmdsInfo(0), | 47 fGLDrawCmdsInfo(0), |
47 fInstanceAttribsBufferUniqueId(SK_InvalidUniqueID) { | 48 fInstanceAttribsBufferUniqueId(SK_InvalidUniqueID) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 fInstanceBuffer.reset( | 112 fInstanceBuffer.reset( |
112 rp->createBuffer(sizeof(Instance) * numGLInstances, kVertex_GrBufferType
, | 113 rp->createBuffer(sizeof(Instance) * numGLInstances, kVertex_GrBufferType
, |
113 kDynamic_GrAccessPattern, | 114 kDynamic_GrAccessPattern, |
114 GrResourceProvider::kNoPendingIO_Flag | | 115 GrResourceProvider::kNoPendingIO_Flag | |
115 GrResourceProvider::kRequireGpuMemory_Flag)); | 116 GrResourceProvider::kRequireGpuMemory_Flag)); |
116 if (!fInstanceBuffer) { | 117 if (!fInstanceBuffer) { |
117 return; | 118 return; |
118 } | 119 } |
119 | 120 |
120 SkASSERT(!fDrawIndirectBuffer); | 121 SkASSERT(!fDrawIndirectBuffer); |
121 fDrawIndirectBuffer.reset( | 122 if (this->glGpu()->glCaps().drawIndirectSupport()) { |
122 rp->createBuffer(sizeof(GrGLDrawElementsIndirectCommand) * numGLDrawCmds
, | 123 fDrawIndirectBuffer.reset( |
123 kDrawIndirect_GrBufferType, kDynamic_GrAccessPattern, | 124 rp->createBuffer(sizeof(GrGLDrawElementsIndirectCommand) * numGLDraw
Cmds, |
124 GrResourceProvider::kNoPendingIO_Flag | | 125 kDrawIndirect_GrBufferType, kDynamic_GrAccessPatter
n, |
125 GrResourceProvider::kRequireGpuMemory_Flag)); | 126 GrResourceProvider::kNoPendingIO_Flag | |
126 if (!fDrawIndirectBuffer) { | 127 GrResourceProvider::kRequireGpuMemory_Flag)); |
127 return; | 128 if (!fDrawIndirectBuffer) { |
| 129 return; |
| 130 } |
128 } | 131 } |
129 | 132 |
130 Instance* glMappedInstances = static_cast<Instance*>(fInstanceBuffer->map())
; | 133 Instance* glMappedInstances = static_cast<Instance*>(fInstanceBuffer->map())
; |
| 134 SkASSERT(glMappedInstances); |
131 int glInstancesIdx = 0; | 135 int glInstancesIdx = 0; |
132 | 136 |
133 auto* glMappedCmds = static_cast<GrGLDrawElementsIndirectCommand*>(fDrawIndi
rectBuffer->map()); | 137 GrGLDrawElementsIndirectCommand* glMappedCmds = nullptr; |
134 int glDrawCmdsIdx = 0; | 138 int glDrawCmdsIdx = 0; |
| 139 if (fDrawIndirectBuffer) { |
| 140 glMappedCmds = static_cast<GrGLDrawElementsIndirectCommand*>(fDrawIndire
ctBuffer->map()); |
| 141 SkASSERT(glMappedCmds); |
| 142 } |
135 | 143 |
136 bool baseInstanceSupport = this->glGpu()->glCaps().baseInstanceSupport(); | 144 bool baseInstanceSupport = this->glGpu()->glCaps().baseInstanceSupport(); |
| 145 SkASSERT(!baseInstanceSupport || fDrawIndirectBuffer); |
137 | 146 |
| 147 SkASSERT(!fGLDrawCmdsInfo); |
138 if (GR_GL_LOG_INSTANCED_BATCHES || !baseInstanceSupport) { | 148 if (GR_GL_LOG_INSTANCED_BATCHES || !baseInstanceSupport) { |
139 fGLDrawCmdsInfo.reset(numGLDrawCmds); | 149 fGLDrawCmdsInfo.reset(numGLDrawCmds); |
140 } | 150 } |
141 | 151 |
142 // Generate the instance and draw-indirect buffer contents based on the trac
ked batches. | 152 // Generate the instance and draw-indirect buffer contents based on the trac
ked batches. |
143 iter.init(this->trackedBatches(), BatchList::Iter::kHead_IterStart); | 153 iter.init(this->trackedBatches(), BatchList::Iter::kHead_IterStart); |
144 while (Batch* b = iter.get()) { | 154 while (Batch* b = iter.get()) { |
145 GLBatch* batch = static_cast<GLBatch*>(b); | 155 GLBatch* batch = static_cast<GLBatch*>(b); |
146 iter.next(); | 156 iter.next(); |
147 | 157 |
148 batch->fEmulatedBaseInstance = baseInstanceSupport ? 0 : glInstancesIdx; | 158 batch->fEmulatedBaseInstance = baseInstanceSupport ? 0 : glInstancesIdx; |
149 batch->fGLDrawCmdsIdx = glDrawCmdsIdx; | 159 batch->fGLDrawCmdsIdx = glDrawCmdsIdx; |
150 | 160 |
151 const Batch::Draw* draw = batch->fHeadDraw; | 161 const Batch::Draw* draw = batch->fHeadDraw; |
152 SkASSERT(draw); | 162 SkASSERT(draw); |
153 do { | 163 do { |
154 int instanceCount = 0; | 164 int instanceCount = 0; |
155 IndexRange geometry = draw->fGeometry; | 165 IndexRange geometry = draw->fGeometry; |
156 SkASSERT(!geometry.isEmpty()); | 166 SkASSERT(!geometry.isEmpty()); |
157 | 167 |
158 do { | 168 do { |
159 glMappedInstances[glInstancesIdx + instanceCount++] = draw->fIns
tance; | 169 glMappedInstances[glInstancesIdx + instanceCount++] = draw->fIns
tance; |
160 draw = draw->fNext; | 170 draw = draw->fNext; |
161 } while (draw && draw->fGeometry == geometry); | 171 } while (draw && draw->fGeometry == geometry); |
162 | 172 |
163 GrGLDrawElementsIndirectCommand& glCmd = glMappedCmds[glDrawCmdsIdx]
; | 173 if (fDrawIndirectBuffer) { |
164 glCmd.fCount = geometry.fCount; | 174 GrGLDrawElementsIndirectCommand& glCmd = glMappedCmds[glDrawCmds
Idx]; |
165 glCmd.fInstanceCount = instanceCount; | 175 glCmd.fCount = geometry.fCount; |
166 glCmd.fFirstIndex = geometry.fStart; | 176 glCmd.fInstanceCount = instanceCount; |
167 glCmd.fBaseVertex = 0; | 177 glCmd.fFirstIndex = geometry.fStart; |
168 glCmd.fBaseInstance = baseInstanceSupport ? glInstancesIdx : 0; | 178 glCmd.fBaseVertex = 0; |
| 179 glCmd.fBaseInstance = baseInstanceSupport ? glInstancesIdx : 0; |
| 180 } |
169 | 181 |
170 if (GR_GL_LOG_INSTANCED_BATCHES || !baseInstanceSupport) { | 182 if (GR_GL_LOG_INSTANCED_BATCHES || !baseInstanceSupport) { |
171 fGLDrawCmdsInfo[glDrawCmdsIdx].fInstanceCount = instanceCount; | 183 GLDrawCmdInfo& cmdInfo = fGLDrawCmdsInfo[glDrawCmdsIdx]; |
172 #if GR_GL_LOG_INSTANCED_BATCHES | 184 cmdInfo.fGeometry = geometry; |
173 fGLDrawCmdsInfo[glDrawCmdsIdx].fGeometry = geometry; | 185 cmdInfo.fInstanceCount = instanceCount; |
174 #endif | |
175 } | 186 } |
176 | 187 |
177 glInstancesIdx += instanceCount; | 188 glInstancesIdx += instanceCount; |
178 ++glDrawCmdsIdx; | 189 ++glDrawCmdsIdx; |
179 } while (draw); | 190 } while (draw); |
180 } | 191 } |
181 | 192 |
182 SkASSERT(glDrawCmdsIdx == numGLDrawCmds); | 193 SkASSERT(glDrawCmdsIdx == numGLDrawCmds); |
183 fDrawIndirectBuffer->unmap(); | 194 if (fDrawIndirectBuffer) { |
| 195 fDrawIndirectBuffer->unmap(); |
| 196 } |
184 | 197 |
185 SkASSERT(glInstancesIdx == numGLInstances); | 198 SkASSERT(glInstancesIdx == numGLInstances); |
186 fInstanceBuffer->unmap(); | 199 fInstanceBuffer->unmap(); |
187 } | 200 } |
188 | 201 |
189 void GLInstancedRendering::onDraw(const GrPipeline& pipeline, const InstanceProc
essor& instProc, | 202 void GLInstancedRendering::onDraw(const GrPipeline& pipeline, const InstanceProc
essor& instProc, |
190 const Batch* baseBatch) { | 203 const Batch* baseBatch) { |
191 if (!fDrawIndirectBuffer) { | 204 if (!fDrawIndirectBuffer && !fGLDrawCmdsInfo) { |
192 return; // beginFlush was not successful. | 205 return; // beginFlush was not successful. |
193 } | 206 } |
194 if (!this->glGpu()->flushGLState(pipeline, instProc)) { | 207 if (!this->glGpu()->flushGLState(pipeline, instProc)) { |
195 return; | 208 return; |
196 } | 209 } |
197 | 210 |
198 this->glGpu()->bindBuffer(kDrawIndirect_GrBufferType, fDrawIndirectBuffer.ge
t()); | 211 if (fDrawIndirectBuffer) { |
| 212 this->glGpu()->bindBuffer(kDrawIndirect_GrBufferType, fDrawIndirectBuffe
r.get()); |
| 213 } |
199 | 214 |
200 const GrGLCaps& glCaps = this->glGpu()->glCaps(); | 215 const GrGLCaps& glCaps = this->glGpu()->glCaps(); |
201 const GLBatch* batch = static_cast<const GLBatch*>(baseBatch); | 216 const GLBatch* batch = static_cast<const GLBatch*>(baseBatch); |
202 int numCommands = batch->numGLCommands(); | 217 int numCommands = batch->numGLCommands(); |
203 | 218 |
204 #if GR_GL_LOG_INSTANCED_BATCHES | 219 #if GR_GL_LOG_INSTANCED_BATCHES |
205 SkASSERT(fGLDrawCmdsInfo); | 220 SkASSERT(fGLDrawCmdsInfo); |
206 SkDebugf("Instanced batch: ["); | 221 SkDebugf("Instanced batch: ["); |
207 for (int i = 0; i < numCommands; ++i) { | 222 for (int i = 0; i < numCommands; ++i) { |
208 int glCmdIdx = batch->fGLDrawCmdsIdx + i; | 223 int glCmdIdx = batch->fGLDrawCmdsIdx + i; |
209 SkDebugf("%s%i * %s", (i ? ", " : ""), fGLDrawCmdsInfo[glCmdIdx].fInsta
nceCount, | 224 SkDebugf("%s%i * %s", (i ? ", " : ""), fGLDrawCmdsInfo[glCmdIdx].fInsta
nceCount, |
210 InstanceProcessor::GetNameOfIndexRange(fGLDrawCmdsInfo[glCmdIdx
].fGeometry)); | 225 InstanceProcessor::GetNameOfIndexRange(fGLDrawCmdsInfo[glCmdIdx
].fGeometry)); |
211 } | 226 } |
212 SkDebugf("]\n"); | 227 SkDebugf("]\n"); |
213 #else | 228 #else |
214 SkASSERT(SkToBool(fGLDrawCmdsInfo) == !glCaps.baseInstanceSupport()); | 229 SkASSERT(SkToBool(fGLDrawCmdsInfo) == !glCaps.baseInstanceSupport()); |
215 #endif | 230 #endif |
216 | 231 |
217 if (1 == numCommands || !glCaps.baseInstanceSupport() || !glCaps.multiDrawIn
directSupport()) { | 232 if (numCommands > 1 && glCaps.multiDrawIndirectSupport() && glCaps.baseInsta
nceSupport()) { |
218 int emulatedBaseInstance = batch->fEmulatedBaseInstance; | 233 SkASSERT(fDrawIndirectBuffer); |
219 for (int i = 0; i < numCommands; ++i) { | |
220 int glCmdIdx = batch->fGLDrawCmdsIdx + i; | |
221 this->flushInstanceAttribs(emulatedBaseInstance); | |
222 GL_CALL(DrawElementsIndirect(GR_GL_TRIANGLES, GR_GL_UNSIGNED_BYTE, | |
223 (GrGLDrawElementsIndirectCommand*) null
ptr + glCmdIdx)); | |
224 if (!glCaps.baseInstanceSupport()) { | |
225 emulatedBaseInstance += fGLDrawCmdsInfo[glCmdIdx].fInstanceCount
; | |
226 } | |
227 } | |
228 } else { | |
229 int glCmdsIdx = batch->fGLDrawCmdsIdx; | 234 int glCmdsIdx = batch->fGLDrawCmdsIdx; |
230 this->flushInstanceAttribs(batch->fEmulatedBaseInstance); | 235 this->flushInstanceAttribs(batch->fEmulatedBaseInstance); |
231 GL_CALL(MultiDrawElementsIndirect(GR_GL_TRIANGLES, GR_GL_UNSIGNED_BYTE, | 236 GL_CALL(MultiDrawElementsIndirect(GR_GL_TRIANGLES, GR_GL_UNSIGNED_BYTE, |
232 (GrGLDrawElementsIndirectCommand*) nul
lptr + glCmdsIdx, | 237 (GrGLDrawElementsIndirectCommand*) nul
lptr + glCmdsIdx, |
233 numCommands, 0)); | 238 numCommands, 0)); |
| 239 return; |
| 240 } |
| 241 |
| 242 int emulatedBaseInstance = batch->fEmulatedBaseInstance; |
| 243 for (int i = 0; i < numCommands; ++i) { |
| 244 int glCmdIdx = batch->fGLDrawCmdsIdx + i; |
| 245 const GLDrawCmdInfo& cmdInfo = fGLDrawCmdsInfo[glCmdIdx]; |
| 246 this->flushInstanceAttribs(emulatedBaseInstance); |
| 247 if (fDrawIndirectBuffer) { |
| 248 GL_CALL(DrawElementsIndirect(GR_GL_TRIANGLES, GR_GL_UNSIGNED_BYTE, |
| 249 (GrGLDrawElementsIndirectCommand*) null
ptr + glCmdIdx)); |
| 250 } else { |
| 251 GL_CALL(DrawElementsInstanced(GR_GL_TRIANGLES, cmdInfo.fGeometry.fCo
unt, |
| 252 GR_GL_UNSIGNED_BYTE, |
| 253 (GrGLubyte*) nullptr + cmdInfo.fGeomet
ry.fStart, |
| 254 cmdInfo.fInstanceCount)); |
| 255 } |
| 256 if (!glCaps.baseInstanceSupport()) { |
| 257 emulatedBaseInstance += cmdInfo.fInstanceCount; |
| 258 } |
234 } | 259 } |
235 } | 260 } |
236 | 261 |
237 void GLInstancedRendering::flushInstanceAttribs(int baseInstance) { | 262 void GLInstancedRendering::flushInstanceAttribs(int baseInstance) { |
238 SkASSERT(fVertexArrayID); | 263 SkASSERT(fVertexArrayID); |
239 this->glGpu()->bindVertexArray(fVertexArrayID); | 264 this->glGpu()->bindVertexArray(fVertexArrayID); |
240 | 265 |
241 SkASSERT(fInstanceBuffer); | 266 SkASSERT(fInstanceBuffer); |
242 if (fInstanceAttribsBufferUniqueId != fInstanceBuffer->getUniqueID() || | 267 if (fInstanceAttribsBufferUniqueId != fInstanceBuffer->getUniqueID() || |
243 fInstanceAttribsBaseInstance != baseInstance) { | 268 fInstanceAttribsBaseInstance != baseInstance) { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 GL_CALL(DeleteVertexArrays(1, &fVertexArrayID)); | 314 GL_CALL(DeleteVertexArrays(1, &fVertexArrayID)); |
290 this->glGpu()->notifyVertexArrayDelete(fVertexArrayID); | 315 this->glGpu()->notifyVertexArrayDelete(fVertexArrayID); |
291 } | 316 } |
292 fVertexArrayID = 0; | 317 fVertexArrayID = 0; |
293 fInstanceBuffer.reset(); | 318 fInstanceBuffer.reset(); |
294 fDrawIndirectBuffer.reset(); | 319 fDrawIndirectBuffer.reset(); |
295 fInstanceAttribsBufferUniqueId = SK_InvalidUniqueID; | 320 fInstanceAttribsBufferUniqueId = SK_InvalidUniqueID; |
296 } | 321 } |
297 | 322 |
298 } | 323 } |
OLD | NEW |