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