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