• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017 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 "src/gpu/ganesh/gl/GrGLOpsRenderPass.h"
9 
10 #include "src/gpu/ganesh/GrProgramInfo.h"
11 #include "src/gpu/ganesh/GrRenderTarget.h"
12 #include "src/gpu/ganesh/gl/GrGLProgram.h"
13 
14 #ifdef SK_DEBUG
15 #include "include/gpu/GrDirectContext.h"
16 #include "src/gpu/ganesh/GrDirectContextPriv.h"
17 #endif
18 
19 #define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
20 
set(GrRenderTarget * rt,bool useMSAASurface,const SkIRect & contentBounds,GrSurfaceOrigin origin,const LoadAndStoreInfo & colorInfo,const StencilLoadAndStoreInfo & stencilInfo)21 void GrGLOpsRenderPass::set(GrRenderTarget* rt, bool useMSAASurface, const SkIRect& contentBounds,
22                             GrSurfaceOrigin origin, const LoadAndStoreInfo& colorInfo,
23                             const StencilLoadAndStoreInfo& stencilInfo) {
24     SkASSERT(fGpu);
25     SkASSERT(!fRenderTarget);
26     SkASSERT(fGpu == rt->getContext()->priv().getGpu());
27 
28     this->INHERITED::set(rt, origin);
29     fUseMultisampleFBO = useMSAASurface;
30     fContentBounds = contentBounds;
31     fColorLoadAndStoreInfo = colorInfo;
32     fStencilLoadAndStoreInfo = stencilInfo;
33 }
34 
dmsaaLoadStoreBounds() const35 GrNativeRect GrGLOpsRenderPass::dmsaaLoadStoreBounds() const {
36     if (fGpu->glCaps().framebufferResolvesMustBeFullSize()) {
37         // If frambeffer resolves have to be full size, then resolve the entire render target during
38         // load and store both, even if we will be doing so with a draw. We do this because we will
39         // have no other choice than to do a full size resolve at the end of the render pass, so the
40         // full DMSAA attachment needs to have valid content.
41         return GrNativeRect::MakeRelativeTo(fOrigin, fRenderTarget->height(),
42                                             SkIRect::MakeSize(fRenderTarget->dimensions()));
43     } else {
44         return GrNativeRect::MakeRelativeTo(fOrigin, fRenderTarget->height(), fContentBounds);
45     }
46 }
47 
onBegin()48 void GrGLOpsRenderPass::onBegin() {
49     auto glRT = static_cast<GrGLRenderTarget*>(fRenderTarget);
50     if (fUseMultisampleFBO &&
51         fColorLoadAndStoreInfo.fLoadOp == GrLoadOp::kLoad &&
52         glRT->hasDynamicMSAAAttachment()) {
53         // Load the single sample fbo into the dmsaa attachment.
54         if (fGpu->glCaps().canResolveSingleToMSAA()) {
55             fGpu->resolveRenderFBOs(glRT, this->dmsaaLoadStoreBounds().asSkIRect(),
56                                     GrGLGpu::ResolveDirection::kSingleToMSAA);
57         } else {
58             fGpu->drawSingleIntoMSAAFBO(glRT, this->dmsaaLoadStoreBounds().asSkIRect());
59         }
60     }
61 
62     fGpu->beginCommandBuffer(glRT, fUseMultisampleFBO, fContentBounds, fOrigin,
63                              fColorLoadAndStoreInfo, fStencilLoadAndStoreInfo);
64 }
65 
onEnd()66 void GrGLOpsRenderPass::onEnd() {
67     auto glRT = static_cast<GrGLRenderTarget*>(fRenderTarget);
68     fGpu->endCommandBuffer(glRT, fUseMultisampleFBO, fColorLoadAndStoreInfo,
69                            fStencilLoadAndStoreInfo);
70 
71     if (fUseMultisampleFBO &&
72         fColorLoadAndStoreInfo.fStoreOp == GrStoreOp::kStore &&
73         glRT->hasDynamicMSAAAttachment()) {
74         // Blit the msaa attachment into the single sample fbo.
75         fGpu->resolveRenderFBOs(glRT, this->dmsaaLoadStoreBounds().asSkIRect(),
76                                 GrGLGpu::ResolveDirection::kMSAAToSingle,
77                                 true /*invalidateReadBufferAfterBlit*/);
78     }
79 }
80 
onBindPipeline(const GrProgramInfo & programInfo,const SkRect & drawBounds)81 bool GrGLOpsRenderPass::onBindPipeline(const GrProgramInfo& programInfo,
82                                        const SkRect& drawBounds) {
83     fPrimitiveType = programInfo.primitiveType();
84     return fGpu->flushGLState(fRenderTarget, fUseMultisampleFBO, programInfo);
85 }
86 
onSetScissorRect(const SkIRect & scissor)87 void GrGLOpsRenderPass::onSetScissorRect(const SkIRect& scissor) {
88     fGpu->flushScissorRect(scissor, fRenderTarget->height(), fOrigin);
89 }
90 
onBindTextures(const GrGeometryProcessor & geomProc,const GrSurfaceProxy * const geomProcTextures[],const GrPipeline & pipeline)91 bool GrGLOpsRenderPass::onBindTextures(const GrGeometryProcessor& geomProc,
92                                        const GrSurfaceProxy* const geomProcTextures[],
93                                        const GrPipeline& pipeline) {
94     GrGLProgram* program = fGpu->currentProgram();
95     SkASSERT(program);
96     program->bindTextures(geomProc, geomProcTextures, pipeline);
97     return true;
98 }
99 
onBindBuffers(sk_sp<const GrBuffer> indexBuffer,sk_sp<const GrBuffer> instanceBuffer,sk_sp<const GrBuffer> vertexBuffer,GrPrimitiveRestart primitiveRestart)100 void GrGLOpsRenderPass::onBindBuffers(sk_sp<const GrBuffer> indexBuffer,
101                                       sk_sp<const GrBuffer> instanceBuffer,
102                                       sk_sp<const GrBuffer> vertexBuffer,
103                                       GrPrimitiveRestart primitiveRestart) {
104     SkASSERT((primitiveRestart == GrPrimitiveRestart::kNo) || indexBuffer);
105     GrGLProgram* program = fGpu->currentProgram();
106     SkASSERT(program);
107 
108 #ifdef SK_DEBUG
109     fDidBindInstanceBuffer = false;
110     fDidBindVertexBuffer = false;
111 #endif
112 
113     int numAttribs = program->numVertexAttributes() + program->numInstanceAttributes();
114     fAttribArrayState = fGpu->bindInternalVertexArray(indexBuffer.get(), numAttribs,
115                                                       primitiveRestart);
116 
117     if (indexBuffer) {
118         if (indexBuffer->isCpuBuffer()) {
119             auto* cpuIndexBuffer = static_cast<const GrCpuBuffer*>(indexBuffer.get());
120             fIndexPointer = reinterpret_cast<const uint16_t*>(cpuIndexBuffer->data());
121         } else {
122             fIndexPointer = nullptr;
123         }
124     }
125 
126     // If this platform does not support baseInstance, defer binding of the instance buffer.
127     if (fGpu->glCaps().baseVertexBaseInstanceSupport()) {
128         this->bindInstanceBuffer(instanceBuffer.get(), 0);
129         SkDEBUGCODE(fDidBindInstanceBuffer = true;)
130     }
131     fActiveInstanceBuffer = std::move(instanceBuffer);
132 
133     // We differ binding the vertex buffer for one of two situations:
134     // 1) This platform does not support baseVertex with indexed draws.
135     // 2) There is a driver bug affecting glDrawArrays.
136     if ((indexBuffer && fGpu->glCaps().baseVertexBaseInstanceSupport()) ||
137         (!indexBuffer && !fGpu->glCaps().drawArraysBaseVertexIsBroken())) {
138             this->bindVertexBuffer(vertexBuffer.get(), 0);
139             SkDEBUGCODE(fDidBindVertexBuffer = true;)
140     }
141     fActiveVertexBuffer = std::move(vertexBuffer);
142     fActiveIndexBuffer = std::move(indexBuffer);
143 }
144 
bindInstanceBuffer(const GrBuffer * instanceBuffer,int baseInstance)145 void GrGLOpsRenderPass::bindInstanceBuffer(const GrBuffer* instanceBuffer, int baseInstance) {
146     GrGLProgram* program = fGpu->currentProgram();
147     SkASSERT(program);
148     if (int instanceStride = program->instanceStride()) {
149         SkASSERT(instanceBuffer);
150         SkASSERT(instanceBuffer->isCpuBuffer() ||
151                  !static_cast<const GrGpuBuffer*>(instanceBuffer)->isMapped());
152         size_t bufferOffset = baseInstance * static_cast<size_t>(instanceStride);
153         int attribIdx = program->numVertexAttributes();
154         for (int i = 0; i < program->numInstanceAttributes(); ++i, ++attribIdx) {
155             const auto& attrib = program->instanceAttribute(i);
156             static constexpr int kDivisor = 1;
157             fAttribArrayState->set(fGpu, attrib.fLocation, instanceBuffer, attrib.fCPUType,
158                                    attrib.fGPUType, instanceStride, bufferOffset + attrib.fOffset,
159                                    kDivisor);
160         }
161     }
162 }
163 
bindVertexBuffer(const GrBuffer * vertexBuffer,int baseVertex)164 void GrGLOpsRenderPass::bindVertexBuffer(const GrBuffer* vertexBuffer, int baseVertex) {
165     GrGLProgram* program = fGpu->currentProgram();
166     SkASSERT(program);
167     if (int vertexStride = program->vertexStride()) {
168         SkASSERT(vertexBuffer);
169         SkASSERT(vertexBuffer->isCpuBuffer() ||
170                  !static_cast<const GrGpuBuffer*>(vertexBuffer)->isMapped());
171         size_t bufferOffset = baseVertex * static_cast<size_t>(vertexStride);
172         for (int i = 0; i < program->numVertexAttributes(); ++i) {
173             const auto& attrib = program->vertexAttribute(i);
174             static constexpr int kDivisor = 0;
175             fAttribArrayState->set(fGpu, attrib.fLocation, vertexBuffer, attrib.fCPUType,
176                                    attrib.fGPUType, vertexStride, bufferOffset + attrib.fOffset,
177                                    kDivisor);
178         }
179     }
180 }
181 
onDraw(int vertexCount,int baseVertex)182 void GrGLOpsRenderPass::onDraw(int vertexCount, int baseVertex) {
183     SkASSERT(fDidBindVertexBuffer || fGpu->glCaps().drawArraysBaseVertexIsBroken());
184     GrGLenum glPrimType = fGpu->prepareToDraw(fPrimitiveType);
185     if (fGpu->glCaps().drawArraysBaseVertexIsBroken()) {
186         this->bindVertexBuffer(fActiveVertexBuffer.get(), baseVertex);
187         baseVertex = 0;
188     }
189     GL_CALL(DrawArrays(glPrimType, baseVertex, vertexCount));
190     fGpu->didDrawTo(fRenderTarget);
191 }
192 
onDrawIndexed(int indexCount,int baseIndex,uint16_t minIndexValue,uint16_t maxIndexValue,int baseVertex)193 void GrGLOpsRenderPass::onDrawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue,
194                                       uint16_t maxIndexValue, int baseVertex) {
195     GrGLenum glPrimType = fGpu->prepareToDraw(fPrimitiveType);
196     if (fGpu->glCaps().baseVertexBaseInstanceSupport()) {
197         SkASSERT(fGpu->glCaps().drawInstancedSupport());
198         SkASSERT(fDidBindVertexBuffer);
199         if (baseVertex != 0) {
200             GL_CALL(DrawElementsInstancedBaseVertexBaseInstance(
201                     glPrimType, indexCount, GR_GL_UNSIGNED_SHORT,
202                     this->offsetForBaseIndex(baseIndex), 1, baseVertex, 0));
203             return;
204         }
205     } else {
206         this->bindVertexBuffer(fActiveVertexBuffer.get(), baseVertex);
207     }
208 
209     if (fGpu->glCaps().drawRangeElementsSupport()) {
210         GL_CALL(DrawRangeElements(glPrimType, minIndexValue, maxIndexValue, indexCount,
211                                   GR_GL_UNSIGNED_SHORT, this->offsetForBaseIndex(baseIndex)));
212     } else {
213         GL_CALL(DrawElements(glPrimType, indexCount, GR_GL_UNSIGNED_SHORT,
214                              this->offsetForBaseIndex(baseIndex)));
215     }
216     fGpu->didDrawTo(fRenderTarget);
217 }
218 
onDrawInstanced(int instanceCount,int baseInstance,int vertexCount,int baseVertex)219 void GrGLOpsRenderPass::onDrawInstanced(int instanceCount, int baseInstance, int vertexCount,
220                                         int baseVertex) {
221     SkASSERT(fDidBindVertexBuffer || fGpu->glCaps().drawArraysBaseVertexIsBroken());
222     if (fGpu->glCaps().drawArraysBaseVertexIsBroken()) {
223         // We weren't able to bind the vertex buffer during onBindBuffers because of a driver bug
224         // affecting glDrawArrays.
225         this->bindVertexBuffer(fActiveVertexBuffer.get(), 0);
226     }
227     int maxInstances = fGpu->glCaps().maxInstancesPerDrawWithoutCrashing(instanceCount);
228     for (int i = 0; i < instanceCount; i += maxInstances) {
229         GrGLenum glPrimType = fGpu->prepareToDraw(fPrimitiveType);
230         int instanceCountForDraw = std::min(instanceCount - i, maxInstances);
231         int baseInstanceForDraw = baseInstance + i;
232         if (fGpu->glCaps().baseVertexBaseInstanceSupport()) {
233             SkASSERT(fDidBindInstanceBuffer);
234             GL_CALL(DrawArraysInstancedBaseInstance(glPrimType, baseVertex, vertexCount,
235                                                     instanceCountForDraw, baseInstanceForDraw));
236         } else {
237             this->bindInstanceBuffer(fActiveInstanceBuffer.get(), baseInstanceForDraw);
238             GL_CALL(DrawArraysInstanced(glPrimType, baseVertex, vertexCount, instanceCountForDraw));
239         }
240     }
241     fGpu->didDrawTo(fRenderTarget);
242 }
243 
onDrawIndexedInstanced(int indexCount,int baseIndex,int instanceCount,int baseInstance,int baseVertex)244 void GrGLOpsRenderPass::onDrawIndexedInstanced(int indexCount, int baseIndex, int instanceCount,
245                                                int baseInstance, int baseVertex) {
246     int maxInstances = fGpu->glCaps().maxInstancesPerDrawWithoutCrashing(instanceCount);
247     for (int i = 0; i < instanceCount; i += maxInstances) {
248         GrGLenum glPrimType = fGpu->prepareToDraw(fPrimitiveType);
249         int instanceCountForDraw = std::min(instanceCount - i, maxInstances);
250         int baseInstanceForDraw = baseInstance + i;
251         if (fGpu->glCaps().baseVertexBaseInstanceSupport()) {
252             SkASSERT(fDidBindInstanceBuffer);
253             SkASSERT(fDidBindVertexBuffer);
254             GL_CALL(DrawElementsInstancedBaseVertexBaseInstance(
255                     glPrimType, indexCount, GR_GL_UNSIGNED_SHORT,
256                     this->offsetForBaseIndex(baseIndex), instanceCountForDraw, baseVertex,
257                     baseInstanceForDraw));
258         } else {
259             this->bindInstanceBuffer(fActiveInstanceBuffer.get(), baseInstanceForDraw);
260             this->bindVertexBuffer(fActiveVertexBuffer.get(), baseVertex);
261             GL_CALL(DrawElementsInstanced(glPrimType, indexCount, GR_GL_UNSIGNED_SHORT,
262                                         this->offsetForBaseIndex(baseIndex), instanceCountForDraw));
263         }
264     }
265     fGpu->didDrawTo(fRenderTarget);
266 }
267 
buffer_offset_to_gl_address(const GrBuffer * drawIndirectBuffer,size_t offset)268 static const void* buffer_offset_to_gl_address(const GrBuffer* drawIndirectBuffer, size_t offset) {
269     if (drawIndirectBuffer->isCpuBuffer()) {
270         return static_cast<const GrCpuBuffer*>(drawIndirectBuffer)->data() + offset;
271     } else {
272         return (offset) ? reinterpret_cast<const void*>(offset) : nullptr;
273     }
274 }
275 
onDrawIndirect(const GrBuffer * drawIndirectBuffer,size_t offset,int drawCount)276 void GrGLOpsRenderPass::onDrawIndirect(const GrBuffer* drawIndirectBuffer, size_t offset,
277                                        int drawCount) {
278     using MultiDrawType = GrGLCaps::MultiDrawType;
279 
280     SkASSERT(fGpu->caps()->nativeDrawIndirectSupport());
281     SkASSERT(fGpu->glCaps().baseVertexBaseInstanceSupport());
282     SkASSERT(fDidBindVertexBuffer || fGpu->glCaps().drawArraysBaseVertexIsBroken());
283 
284     if (fGpu->glCaps().drawArraysBaseVertexIsBroken()) {
285         // We weren't able to bind the vertex buffer during onBindBuffers because of a driver bug
286         // affecting glDrawArrays.
287         this->bindVertexBuffer(fActiveVertexBuffer.get(), 0);
288     }
289 
290     if (fGpu->glCaps().multiDrawType() == MultiDrawType::kANGLEOrWebGL) {
291         // ANGLE and WebGL don't support glDrawElementsIndirect. We draw everything as a multi draw.
292         this->multiDrawArraysANGLEOrWebGL(drawIndirectBuffer, offset, drawCount);
293         return;
294     }
295 
296     fGpu->bindBuffer(GrGpuBufferType::kDrawIndirect, drawIndirectBuffer);
297 
298     if (drawCount > 1 && fGpu->glCaps().multiDrawType() == MultiDrawType::kMultiDrawIndirect) {
299         GrGLenum glPrimType = fGpu->prepareToDraw(fPrimitiveType);
300         GL_CALL(MultiDrawArraysIndirect(glPrimType,
301                                         buffer_offset_to_gl_address(drawIndirectBuffer, offset),
302                                         drawCount, sizeof(GrDrawIndirectCommand)));
303         return;
304     }
305 
306     for (int i = 0; i < drawCount; ++i) {
307         GrGLenum glPrimType = fGpu->prepareToDraw(fPrimitiveType);
308         GL_CALL(DrawArraysIndirect(glPrimType,
309                                    buffer_offset_to_gl_address(drawIndirectBuffer, offset)));
310         offset += sizeof(GrDrawIndirectCommand);
311     }
312     fGpu->didDrawTo(fRenderTarget);
313 }
314 
multiDrawArraysANGLEOrWebGL(const GrBuffer * drawIndirectBuffer,size_t offset,int drawCount)315 void GrGLOpsRenderPass::multiDrawArraysANGLEOrWebGL(const GrBuffer* drawIndirectBuffer,
316                                                     size_t offset, int drawCount) {
317     SkASSERT(fGpu->glCaps().multiDrawType() == GrGLCaps::MultiDrawType::kANGLEOrWebGL);
318     SkASSERT(drawIndirectBuffer->isCpuBuffer());
319 
320     constexpr static int kMaxDrawCountPerBatch = 128;
321     GrGLint fFirsts[kMaxDrawCountPerBatch];
322     GrGLsizei fCounts[kMaxDrawCountPerBatch];
323     GrGLsizei fInstanceCounts[kMaxDrawCountPerBatch];
324     GrGLuint fBaseInstances[kMaxDrawCountPerBatch];
325 
326     GrGLenum glPrimType = fGpu->prepareToDraw(fPrimitiveType);
327     auto* cpuBuffer = static_cast<const GrCpuBuffer*>(drawIndirectBuffer);
328     auto* cmds = reinterpret_cast<const GrDrawIndirectCommand*>(cpuBuffer->data() + offset);
329 
330     while (drawCount) {
331         int countInBatch = std::min(drawCount, kMaxDrawCountPerBatch);
332         for (int i = 0; i < countInBatch; ++i) {
333             auto [vertexCount, instanceCount, baseVertex, baseInstance] = cmds[i];
334             fFirsts[i] = baseVertex;
335             fCounts[i] = vertexCount;
336             fInstanceCounts[i] = instanceCount;
337             fBaseInstances[i] = baseInstance;
338         }
339         if (countInBatch == 1) {
340             GL_CALL(DrawArraysInstancedBaseInstance(glPrimType, fFirsts[0], fCounts[0],
341                                                     fInstanceCounts[0], fBaseInstances[0]));
342         } else {
343             GL_CALL(MultiDrawArraysInstancedBaseInstance(glPrimType, fFirsts, fCounts,
344                                                          fInstanceCounts, fBaseInstances,
345                                                          countInBatch));
346         }
347         drawCount -= countInBatch;
348         cmds += countInBatch;
349     }
350     fGpu->didDrawTo(fRenderTarget);
351 }
352 
onDrawIndexedIndirect(const GrBuffer * drawIndirectBuffer,size_t offset,int drawCount)353 void GrGLOpsRenderPass::onDrawIndexedIndirect(const GrBuffer* drawIndirectBuffer, size_t offset,
354                                               int drawCount) {
355     using MultiDrawType = GrGLCaps::MultiDrawType;
356 
357     SkASSERT(fGpu->caps()->nativeDrawIndirectSupport());
358     SkASSERT(!fGpu->caps()->nativeDrawIndexedIndirectIsBroken());
359     SkASSERT(fGpu->glCaps().baseVertexBaseInstanceSupport());
360     // The vertex buffer should have already gotten bound (as opposed us stashing it away during
361     // onBindBuffers and not expecting to bind it until this point).
362     SkASSERT(fDidBindVertexBuffer);
363 
364     if (fGpu->glCaps().multiDrawType() == MultiDrawType::kANGLEOrWebGL) {
365         // ANGLE and WebGL don't support glDrawElementsIndirect. We draw everything as a multi draw.
366         this->multiDrawElementsANGLEOrWebGL(drawIndirectBuffer, offset, drawCount);
367         return;
368     }
369 
370     fGpu->bindBuffer(GrGpuBufferType::kDrawIndirect, drawIndirectBuffer);
371 
372     if (drawCount > 1 && fGpu->glCaps().multiDrawType() == MultiDrawType::kMultiDrawIndirect) {
373         GrGLenum glPrimType = fGpu->prepareToDraw(fPrimitiveType);
374         GL_CALL(MultiDrawElementsIndirect(glPrimType, GR_GL_UNSIGNED_SHORT,
375                                           buffer_offset_to_gl_address(drawIndirectBuffer, offset),
376                                           drawCount, sizeof(GrDrawIndexedIndirectCommand)));
377         return;
378     }
379 
380     for (int i = 0; i < drawCount; ++i) {
381         GrGLenum glPrimType = fGpu->prepareToDraw(fPrimitiveType);
382         GL_CALL(DrawElementsIndirect(glPrimType, GR_GL_UNSIGNED_SHORT,
383                                      buffer_offset_to_gl_address(drawIndirectBuffer, offset)));
384         offset += sizeof(GrDrawIndexedIndirectCommand);
385     }
386     fGpu->didDrawTo(fRenderTarget);
387 }
388 
multiDrawElementsANGLEOrWebGL(const GrBuffer * drawIndirectBuffer,size_t offset,int drawCount)389 void GrGLOpsRenderPass::multiDrawElementsANGLEOrWebGL(const GrBuffer* drawIndirectBuffer,
390                                                       size_t offset, int drawCount) {
391     SkASSERT(fGpu->glCaps().multiDrawType() == GrGLCaps::MultiDrawType::kANGLEOrWebGL);
392     SkASSERT(drawIndirectBuffer->isCpuBuffer());
393 
394     constexpr static int kMaxDrawCountPerBatch = 128;
395     GrGLint fCounts[kMaxDrawCountPerBatch];
396     const void* fIndices[kMaxDrawCountPerBatch];
397     GrGLsizei fInstanceCounts[kMaxDrawCountPerBatch];
398     GrGLint fBaseVertices[kMaxDrawCountPerBatch];
399     GrGLuint fBaseInstances[kMaxDrawCountPerBatch];
400 
401     GrGLenum glPrimType = fGpu->prepareToDraw(fPrimitiveType);
402     auto* cpuBuffer = static_cast<const GrCpuBuffer*>(drawIndirectBuffer);
403     auto* cmds = reinterpret_cast<const GrDrawIndexedIndirectCommand*>(cpuBuffer->data() + offset);
404 
405     while (drawCount) {
406         int countInBatch = std::min(drawCount, kMaxDrawCountPerBatch);
407         for (int i = 0; i < countInBatch; ++i) {
408             auto [indexCount, instanceCount, baseIndex, baseVertex, baseInstance] = cmds[i];
409             fCounts[i] = indexCount;
410             fIndices[i] = this->offsetForBaseIndex(baseIndex);
411             fInstanceCounts[i] = instanceCount;
412             fBaseVertices[i] = baseVertex;
413             fBaseInstances[i] = baseInstance;
414         }
415         if (countInBatch == 1) {
416             GL_CALL(DrawElementsInstancedBaseVertexBaseInstance(glPrimType, fCounts[0],
417                                                                 GR_GL_UNSIGNED_SHORT, fIndices[0],
418                                                                 fInstanceCounts[0],
419                                                                 fBaseVertices[0],
420                                                                 fBaseInstances[0]));
421         } else {
422             GL_CALL(MultiDrawElementsInstancedBaseVertexBaseInstance(glPrimType, fCounts,
423                                                                      GR_GL_UNSIGNED_SHORT, fIndices,
424                                                                      fInstanceCounts, fBaseVertices,
425                                                                      fBaseInstances, countInBatch));
426         }
427         drawCount -= countInBatch;
428         cmds += countInBatch;
429     }
430     fGpu->didDrawTo(fRenderTarget);
431 }
432 
onClear(const GrScissorState & scissor,std::array<float,4> color)433 void GrGLOpsRenderPass::onClear(const GrScissorState& scissor, std::array<float, 4> color) {
434     fGpu->clear(scissor, color, fRenderTarget, fUseMultisampleFBO, fOrigin);
435 }
436 
onClearStencilClip(const GrScissorState & scissor,bool insideStencilMask)437 void GrGLOpsRenderPass::onClearStencilClip(const GrScissorState& scissor, bool insideStencilMask) {
438     fGpu->clearStencilClip(scissor, insideStencilMask, fRenderTarget, fUseMultisampleFBO, fOrigin);
439 }
440