GLInstancedRendering.cpp revision e3302dfb81865051ad19cd1c91e2ec3a27df3417
1a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton/* 2a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton * Copyright 2016 Google Inc. 3a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton * 4a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton * Use of this source code is governed by a BSD-style license that can be 5a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton * found in the LICENSE file. 6a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton */ 7a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 8a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton#include "GLInstancedRendering.h" 9a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 10a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton#include "GrResourceProvider.h" 11a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton#include "gl/GrGLGpu.h" 12a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton#include "instanced/InstanceProcessor.h" 13a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 14a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton#define GL_CALL(X) GR_GL_CALL(this->glGpu()->glInterface(), X) 15a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 16a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdaltonnamespace gr_instanced { 17a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 18e3302dfb81865051ad19cd1c91e2ec3a27df3417Robert Phillipsclass GLInstancedOp final : public InstancedOp { 19a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdaltonpublic: 2025a880960a9a689a745a01071ecba3fe494b5940Brian Salomon DEFINE_OP_CLASS_ID 21a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 22e3302dfb81865051ad19cd1c91e2ec3a27df3417Robert Phillips GLInstancedOp(GLOpAllocator* alloc, GrPaint&& paint) 23e3302dfb81865051ad19cd1c91e2ec3a27df3417Robert Phillips : INHERITED(ClassID(), std::move(paint), alloc) { 24e3302dfb81865051ad19cd1c91e2ec3a27df3417Robert Phillips } 25a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton int numGLCommands() const { return 1 + fNumChangesInGeometry; } 26a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 27a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdaltonprivate: 28a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton int fEmulatedBaseInstance; 29a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton int fGLDrawCmdsIdx; 30a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 31a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton friend class GLInstancedRendering; 32a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 33e3302dfb81865051ad19cd1c91e2ec3a27df3417Robert Phillips typedef InstancedOp INHERITED; 34a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton}; 35a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 36e0d362929d6569e8737d80dead791c640390e819csmartdaltonGrCaps::InstancedSupport GLInstancedRendering::CheckSupport(const GrGLCaps& glCaps) { 37e0d362929d6569e8737d80dead791c640390e819csmartdalton // This method is only intended to be used for initializing fInstancedSupport in the caps. 38e0d362929d6569e8737d80dead791c640390e819csmartdalton SkASSERT(GrCaps::InstancedSupport::kNone == glCaps.instancedSupport()); 394c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton if (!glCaps.vertexArrayObjectSupport() || 404c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton (!glCaps.drawIndirectSupport() && !glCaps.drawInstancedSupport())) { 41e0d362929d6569e8737d80dead791c640390e819csmartdalton return GrCaps::InstancedSupport::kNone; 42a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 431edc5b92fecefb79f01cf0e302646eacf32b06c7Brian Salomon return InstanceProcessor::CheckSupport(*glCaps.shaderCaps(), glCaps); 44a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton} 45a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 46e0d362929d6569e8737d80dead791c640390e819csmartdaltonGLInstancedRendering::GLInstancedRendering(GrGLGpu* gpu) 47e3302dfb81865051ad19cd1c91e2ec3a27df3417Robert Phillips : INHERITED(gpu) 48e3302dfb81865051ad19cd1c91e2ec3a27df3417Robert Phillips , fVertexArrayID(0) 49e3302dfb81865051ad19cd1c91e2ec3a27df3417Robert Phillips , fGLDrawCmdsInfo(0) 50e3302dfb81865051ad19cd1c91e2ec3a27df3417Robert Phillips , fInstanceAttribsBufferUniqueId(SK_InvalidUniqueID) { 51e0d362929d6569e8737d80dead791c640390e819csmartdalton SkASSERT(GrCaps::InstancedSupport::kNone != this->gpu()->caps()->instancedSupport()); 52a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton} 53a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 54a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdaltonGLInstancedRendering::~GLInstancedRendering() { 55a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton if (fVertexArrayID) { 56a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(DeleteVertexArrays(1, &fVertexArrayID)); 57a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton this->glGpu()->notifyVertexArrayDelete(fVertexArrayID); 58a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 59a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton} 60a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 61a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdaltoninline GrGLGpu* GLInstancedRendering::glGpu() const { 62a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton return static_cast<GrGLGpu*>(this->gpu()); 63a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton} 64a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 65e3302dfb81865051ad19cd1c91e2ec3a27df3417Robert Phillipsstd::unique_ptr<InstancedOp> GLOpAllocator::makeOp(GrPaint&& paint) { 66e3302dfb81865051ad19cd1c91e2ec3a27df3417Robert Phillips return std::unique_ptr<InstancedOp>(new GLInstancedOp(this, std::move(paint))); 67f8334781914363caf537f22f012fcd5c03c60dadBrian Salomon} 68a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 69a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdaltonvoid GLInstancedRendering::onBeginFlush(GrResourceProvider* rp) { 70a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton // Count what there is to draw. 7199ad164886ba39f688ebabecd5fe20dd5d923ba0Brian Salomon OpList::Iter iter; 7299ad164886ba39f688ebabecd5fe20dd5d923ba0Brian Salomon iter.init(this->trackedOps(), OpList::Iter::kHead_IterStart); 73a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton int numGLInstances = 0; 74a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton int numGLDrawCmds = 0; 75e3302dfb81865051ad19cd1c91e2ec3a27df3417Robert Phillips while (InstancedOp* o = iter.get()) { 76e3302dfb81865051ad19cd1c91e2ec3a27df3417Robert Phillips GLInstancedOp* op = (GLInstancedOp*) o; 77a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton iter.next(); 78a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 7999ad164886ba39f688ebabecd5fe20dd5d923ba0Brian Salomon numGLInstances += op->fNumDraws; 8099ad164886ba39f688ebabecd5fe20dd5d923ba0Brian Salomon numGLDrawCmds += op->numGLCommands(); 81a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 82a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton if (!numGLDrawCmds) { 83a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton return; 84a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 85a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton SkASSERT(numGLInstances); 86a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 87a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton // Lazily create a vertex array object. 88a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton if (!fVertexArrayID) { 89a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(GenVertexArrays(1, &fVertexArrayID)); 90a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton if (!fVertexArrayID) { 91a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton return; 92a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 93a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton this->glGpu()->bindVertexArray(fVertexArrayID); 94a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 95a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton // Attach our index buffer to the vertex array. 96485a12003ab48b54965d6f7172f3183358919d8ecsmartdalton SkASSERT(!this->indexBuffer()->isCPUBacked()); 97a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 98a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton static_cast<const GrGLBuffer*>(this->indexBuffer())->bufferID())); 99a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 100a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton // Set up the non-instanced attribs. 101485a12003ab48b54965d6f7172f3183358919d8ecsmartdalton this->glGpu()->bindBuffer(kVertex_GrBufferType, this->vertexBuffer()); 102a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(EnableVertexAttribArray((int)Attrib::kShapeCoords)); 103a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(VertexAttribPointer((int)Attrib::kShapeCoords, 2, GR_GL_FLOAT, GR_GL_FALSE, 104a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton sizeof(ShapeVertex), (void*) offsetof(ShapeVertex, fX))); 105a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(EnableVertexAttribArray((int)Attrib::kVertexAttrs)); 106a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(VertexAttribIPointer((int)Attrib::kVertexAttrs, 1, GR_GL_INT, sizeof(ShapeVertex), 107a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton (void*) offsetof(ShapeVertex, fAttrs))); 108a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 109294870ff119b89fc902773643b054f14e5d1f554Robert Phillips SkASSERT(fInstanceAttribsBufferUniqueId.isInvalid()); 110a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 111a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 112a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton // Create and map instance and draw-indirect buffers. 113a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton SkASSERT(!fInstanceBuffer); 114485a12003ab48b54965d6f7172f3183358919d8ecsmartdalton fInstanceBuffer.reset( 115a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton rp->createBuffer(sizeof(Instance) * numGLInstances, kVertex_GrBufferType, 116485a12003ab48b54965d6f7172f3183358919d8ecsmartdalton kDynamic_GrAccessPattern, 117485a12003ab48b54965d6f7172f3183358919d8ecsmartdalton GrResourceProvider::kNoPendingIO_Flag | 118485a12003ab48b54965d6f7172f3183358919d8ecsmartdalton GrResourceProvider::kRequireGpuMemory_Flag)); 119a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton if (!fInstanceBuffer) { 120a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton return; 121a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 122a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 123a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton SkASSERT(!fDrawIndirectBuffer); 1244c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton if (this->glGpu()->glCaps().drawIndirectSupport()) { 1254c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton fDrawIndirectBuffer.reset( 1264c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton rp->createBuffer(sizeof(GrGLDrawElementsIndirectCommand) * numGLDrawCmds, 1274c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton kDrawIndirect_GrBufferType, kDynamic_GrAccessPattern, 1284c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton GrResourceProvider::kNoPendingIO_Flag | 1294c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton GrResourceProvider::kRequireGpuMemory_Flag)); 1304c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton if (!fDrawIndirectBuffer) { 1314c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton return; 1324c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton } 133a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 134a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 135a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton Instance* glMappedInstances = static_cast<Instance*>(fInstanceBuffer->map()); 1364c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton SkASSERT(glMappedInstances); 137a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton int glInstancesIdx = 0; 138a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 1394c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton GrGLDrawElementsIndirectCommand* glMappedCmds = nullptr; 140a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton int glDrawCmdsIdx = 0; 1414c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton if (fDrawIndirectBuffer) { 1424c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton glMappedCmds = static_cast<GrGLDrawElementsIndirectCommand*>(fDrawIndirectBuffer->map()); 1434c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton SkASSERT(glMappedCmds); 1444c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton } 145a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 146a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton bool baseInstanceSupport = this->glGpu()->glCaps().baseInstanceSupport(); 1474c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton SkASSERT(!baseInstanceSupport || fDrawIndirectBuffer); 148a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 1494c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton SkASSERT(!fGLDrawCmdsInfo); 15099ad164886ba39f688ebabecd5fe20dd5d923ba0Brian Salomon if (GR_GL_LOG_INSTANCED_OPS || !baseInstanceSupport) { 151a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton fGLDrawCmdsInfo.reset(numGLDrawCmds); 152a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 153a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 15499ad164886ba39f688ebabecd5fe20dd5d923ba0Brian Salomon // Generate the instance and draw-indirect buffer contents based on the tracked ops. 15599ad164886ba39f688ebabecd5fe20dd5d923ba0Brian Salomon iter.init(this->trackedOps(), OpList::Iter::kHead_IterStart); 156e3302dfb81865051ad19cd1c91e2ec3a27df3417Robert Phillips while (InstancedOp* o = iter.get()) { 157e3302dfb81865051ad19cd1c91e2ec3a27df3417Robert Phillips GLInstancedOp* op = static_cast<GLInstancedOp*>(o); 158a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton iter.next(); 159a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 16099ad164886ba39f688ebabecd5fe20dd5d923ba0Brian Salomon op->fEmulatedBaseInstance = baseInstanceSupport ? 0 : glInstancesIdx; 16199ad164886ba39f688ebabecd5fe20dd5d923ba0Brian Salomon op->fGLDrawCmdsIdx = glDrawCmdsIdx; 162a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 163e3302dfb81865051ad19cd1c91e2ec3a27df3417Robert Phillips const InstancedOp::Draw* draw = op->fHeadDraw; 164a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton SkASSERT(draw); 165a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton do { 166a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton int instanceCount = 0; 167a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton IndexRange geometry = draw->fGeometry; 168a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton SkASSERT(!geometry.isEmpty()); 169a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 170a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton do { 171a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton glMappedInstances[glInstancesIdx + instanceCount++] = draw->fInstance; 172a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton draw = draw->fNext; 173a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } while (draw && draw->fGeometry == geometry); 174a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 1754c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton if (fDrawIndirectBuffer) { 1764c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton GrGLDrawElementsIndirectCommand& glCmd = glMappedCmds[glDrawCmdsIdx]; 1774c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton glCmd.fCount = geometry.fCount; 1784c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton glCmd.fInstanceCount = instanceCount; 1794c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton glCmd.fFirstIndex = geometry.fStart; 1804c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton glCmd.fBaseVertex = 0; 1814c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton glCmd.fBaseInstance = baseInstanceSupport ? glInstancesIdx : 0; 1824c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton } 183a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 18499ad164886ba39f688ebabecd5fe20dd5d923ba0Brian Salomon if (GR_GL_LOG_INSTANCED_OPS || !baseInstanceSupport) { 1854c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton GLDrawCmdInfo& cmdInfo = fGLDrawCmdsInfo[glDrawCmdsIdx]; 1864c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton cmdInfo.fGeometry = geometry; 1874c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton cmdInfo.fInstanceCount = instanceCount; 188a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 189a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 190a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton glInstancesIdx += instanceCount; 191a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton ++glDrawCmdsIdx; 192a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } while (draw); 193a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 194a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 195a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton SkASSERT(glDrawCmdsIdx == numGLDrawCmds); 1964c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton if (fDrawIndirectBuffer) { 1974c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton fDrawIndirectBuffer->unmap(); 1984c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton } 199a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 200a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton SkASSERT(glInstancesIdx == numGLInstances); 201a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton fInstanceBuffer->unmap(); 202a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton} 203a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 204a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdaltonvoid GLInstancedRendering::onDraw(const GrPipeline& pipeline, const InstanceProcessor& instProc, 205e3302dfb81865051ad19cd1c91e2ec3a27df3417Robert Phillips const InstancedOp* baseOp) { 2064c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton if (!fDrawIndirectBuffer && !fGLDrawCmdsInfo) { 207a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton return; // beginFlush was not successful. 208a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 2092eda5b3a65f54105ae3776160373eed5500c515fbsalomon if (!this->glGpu()->flushGLState(pipeline, instProc, false)) { 210a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton return; 211a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 212a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 2134c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton if (fDrawIndirectBuffer) { 2144c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton this->glGpu()->bindBuffer(kDrawIndirect_GrBufferType, fDrawIndirectBuffer.get()); 2154c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton } 216a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 217a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton const GrGLCaps& glCaps = this->glGpu()->glCaps(); 218e3302dfb81865051ad19cd1c91e2ec3a27df3417Robert Phillips const GLInstancedOp* op = static_cast<const GLInstancedOp*>(baseOp); 21999ad164886ba39f688ebabecd5fe20dd5d923ba0Brian Salomon int numCommands = op->numGLCommands(); 220a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 22199ad164886ba39f688ebabecd5fe20dd5d923ba0Brian Salomon#if GR_GL_LOG_INSTANCED_OPS 222a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton SkASSERT(fGLDrawCmdsInfo); 22399ad164886ba39f688ebabecd5fe20dd5d923ba0Brian Salomon SkDebugf("Instanced op: ["); 224a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton for (int i = 0; i < numCommands; ++i) { 22599ad164886ba39f688ebabecd5fe20dd5d923ba0Brian Salomon int glCmdIdx = op->fGLDrawCmdsIdx + i; 226a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton SkDebugf("%s%i * %s", (i ? ", " : ""), fGLDrawCmdsInfo[glCmdIdx].fInstanceCount, 227a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton InstanceProcessor::GetNameOfIndexRange(fGLDrawCmdsInfo[glCmdIdx].fGeometry)); 228a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 229a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton SkDebugf("]\n"); 230a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton#else 231a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton SkASSERT(SkToBool(fGLDrawCmdsInfo) == !glCaps.baseInstanceSupport()); 232a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton#endif 233a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 2344c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton if (numCommands > 1 && glCaps.multiDrawIndirectSupport() && glCaps.baseInstanceSupport()) { 2354c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton SkASSERT(fDrawIndirectBuffer); 23699ad164886ba39f688ebabecd5fe20dd5d923ba0Brian Salomon int glCmdsIdx = op->fGLDrawCmdsIdx; 23799ad164886ba39f688ebabecd5fe20dd5d923ba0Brian Salomon this->flushInstanceAttribs(op->fEmulatedBaseInstance); 238a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(MultiDrawElementsIndirect(GR_GL_TRIANGLES, GR_GL_UNSIGNED_BYTE, 239a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton (GrGLDrawElementsIndirectCommand*) nullptr + glCmdsIdx, 240a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton numCommands, 0)); 2414c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton return; 2424c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton } 2434c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton 24499ad164886ba39f688ebabecd5fe20dd5d923ba0Brian Salomon int emulatedBaseInstance = op->fEmulatedBaseInstance; 2454c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton for (int i = 0; i < numCommands; ++i) { 24699ad164886ba39f688ebabecd5fe20dd5d923ba0Brian Salomon int glCmdIdx = op->fGLDrawCmdsIdx + i; 2474c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton this->flushInstanceAttribs(emulatedBaseInstance); 2484c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton if (fDrawIndirectBuffer) { 2494c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton GL_CALL(DrawElementsIndirect(GR_GL_TRIANGLES, GR_GL_UNSIGNED_BYTE, 2504c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton (GrGLDrawElementsIndirectCommand*) nullptr + glCmdIdx)); 2514c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton } else { 25235b26a457100804b7a782cdff1132d2b65176c35mtklein const GLDrawCmdInfo& cmdInfo = fGLDrawCmdsInfo[glCmdIdx]; 2534c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton GL_CALL(DrawElementsInstanced(GR_GL_TRIANGLES, cmdInfo.fGeometry.fCount, 2544c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton GR_GL_UNSIGNED_BYTE, 2554c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton (GrGLubyte*) nullptr + cmdInfo.fGeometry.fStart, 2564c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton cmdInfo.fInstanceCount)); 2574c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton } 2584c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton if (!glCaps.baseInstanceSupport()) { 25935b26a457100804b7a782cdff1132d2b65176c35mtklein const GLDrawCmdInfo& cmdInfo = fGLDrawCmdsInfo[glCmdIdx]; 2604c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton emulatedBaseInstance += cmdInfo.fInstanceCount; 2614c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton } 262a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 263a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton} 264a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 265a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdaltonvoid GLInstancedRendering::flushInstanceAttribs(int baseInstance) { 266a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton SkASSERT(fVertexArrayID); 267a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton this->glGpu()->bindVertexArray(fVertexArrayID); 268a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 269a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton SkASSERT(fInstanceBuffer); 2708abb370aca280516f4861c6c942ec453aad018farobertphillips if (fInstanceAttribsBufferUniqueId != fInstanceBuffer->uniqueID() || 271a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton fInstanceAttribsBaseInstance != baseInstance) { 272a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton Instance* offsetInBuffer = (Instance*) nullptr + baseInstance; 273a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 274a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton this->glGpu()->bindBuffer(kVertex_GrBufferType, fInstanceBuffer.get()); 275a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 276a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton // Info attrib. 277a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(EnableVertexAttribArray((int)Attrib::kInstanceInfo)); 278a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(VertexAttribIPointer((int)Attrib::kInstanceInfo, 1, GR_GL_UNSIGNED_INT, 279a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton sizeof(Instance), &offsetInBuffer->fInfo)); 280a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(VertexAttribDivisor((int)Attrib::kInstanceInfo, 1)); 281a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 282a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton // Shape matrix attrib. 283a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(EnableVertexAttribArray((int)Attrib::kShapeMatrixX)); 284a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(EnableVertexAttribArray((int)Attrib::kShapeMatrixY)); 285a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(VertexAttribPointer((int)Attrib::kShapeMatrixX, 3, GR_GL_FLOAT, GR_GL_FALSE, 286a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton sizeof(Instance), &offsetInBuffer->fShapeMatrix2x3[0])); 287a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(VertexAttribPointer((int)Attrib::kShapeMatrixY, 3, GR_GL_FLOAT, GR_GL_FALSE, 288a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton sizeof(Instance), &offsetInBuffer->fShapeMatrix2x3[3])); 289a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(VertexAttribDivisor((int)Attrib::kShapeMatrixX, 1)); 290a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(VertexAttribDivisor((int)Attrib::kShapeMatrixY, 1)); 291a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 292a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton // Color attrib. 293a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(EnableVertexAttribArray((int)Attrib::kColor)); 294a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(VertexAttribPointer((int)Attrib::kColor, 4, GR_GL_UNSIGNED_BYTE, GR_GL_TRUE, 295a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton sizeof(Instance), &offsetInBuffer->fColor)); 296a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(VertexAttribDivisor((int)Attrib::kColor, 1)); 297a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 298a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton // Local rect attrib. 299a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(EnableVertexAttribArray((int)Attrib::kLocalRect)); 300a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(VertexAttribPointer((int)Attrib::kLocalRect, 4, GR_GL_FLOAT, GR_GL_FALSE, 301a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton sizeof(Instance), &offsetInBuffer->fLocalRect)); 302a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(VertexAttribDivisor((int)Attrib::kLocalRect, 1)); 303a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 3048abb370aca280516f4861c6c942ec453aad018farobertphillips fInstanceAttribsBufferUniqueId = fInstanceBuffer->uniqueID(); 305a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton fInstanceAttribsBaseInstance = baseInstance; 306a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 307a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton} 308a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 309a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdaltonvoid GLInstancedRendering::onEndFlush() { 310a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton fInstanceBuffer.reset(); 311a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton fDrawIndirectBuffer.reset(); 312a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton fGLDrawCmdsInfo.reset(0); 313a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton} 314a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 315a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdaltonvoid GLInstancedRendering::onResetGpuResources(ResetType resetType) { 316a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton if (fVertexArrayID && ResetType::kDestroy == resetType) { 317a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(DeleteVertexArrays(1, &fVertexArrayID)); 318a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton this->glGpu()->notifyVertexArrayDelete(fVertexArrayID); 319a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 320a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton fVertexArrayID = 0; 321a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton fInstanceBuffer.reset(); 322a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton fDrawIndirectBuffer.reset(); 323294870ff119b89fc902773643b054f14e5d1f554Robert Phillips fInstanceAttribsBufferUniqueId.makeInvalid(); 324a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton} 325a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 326a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton} 327