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