GLInstancedRendering.cpp revision 35b26a457100804b7a782cdff1132d2b65176c35
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 18a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdaltonclass GLInstancedRendering::GLBatch : public InstancedRendering::Batch { 19a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdaltonpublic: 20a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton DEFINE_BATCH_CLASS_ID 21a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 22a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GLBatch(GLInstancedRendering* instRendering) : INHERITED(ClassID(), instRendering) {} 23a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton int numGLCommands() const { return 1 + fNumChangesInGeometry; } 24a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 25a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdaltonprivate: 26a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton int fEmulatedBaseInstance; 27a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton int fGLDrawCmdsIdx; 28a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 29a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton friend class GLInstancedRendering; 30a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 31a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton typedef Batch INHERITED; 32a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton}; 33a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 34e0d362929d6569e8737d80dead791c640390e819csmartdaltonGrCaps::InstancedSupport GLInstancedRendering::CheckSupport(const GrGLCaps& glCaps) { 35e0d362929d6569e8737d80dead791c640390e819csmartdalton // This method is only intended to be used for initializing fInstancedSupport in the caps. 36e0d362929d6569e8737d80dead791c640390e819csmartdalton SkASSERT(GrCaps::InstancedSupport::kNone == glCaps.instancedSupport()); 374c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton if (!glCaps.vertexArrayObjectSupport() || 384c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton (!glCaps.drawIndirectSupport() && !glCaps.drawInstancedSupport())) { 39e0d362929d6569e8737d80dead791c640390e819csmartdalton return GrCaps::InstancedSupport::kNone; 40a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 41e0d362929d6569e8737d80dead791c640390e819csmartdalton return InstanceProcessor::CheckSupport(*glCaps.glslCaps(), glCaps); 42a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton} 43a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 44e0d362929d6569e8737d80dead791c640390e819csmartdaltonGLInstancedRendering::GLInstancedRendering(GrGLGpu* gpu) 45e0d362929d6569e8737d80dead791c640390e819csmartdalton : INHERITED(gpu), 46a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton fVertexArrayID(0), 47a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton fGLDrawCmdsInfo(0), 48a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton fInstanceAttribsBufferUniqueId(SK_InvalidUniqueID) { 49e0d362929d6569e8737d80dead791c640390e819csmartdalton SkASSERT(GrCaps::InstancedSupport::kNone != this->gpu()->caps()->instancedSupport()); 50a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton} 51a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 52a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdaltonGLInstancedRendering::~GLInstancedRendering() { 53a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton if (fVertexArrayID) { 54a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(DeleteVertexArrays(1, &fVertexArrayID)); 55a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton this->glGpu()->notifyVertexArrayDelete(fVertexArrayID); 56a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 57a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton} 58a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 59a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdaltoninline GrGLGpu* GLInstancedRendering::glGpu() const { 60a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton return static_cast<GrGLGpu*>(this->gpu()); 61a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton} 62a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 63a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdaltonInstancedRendering::Batch* GLInstancedRendering::createBatch() { 64a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton return new GLBatch(this); 65a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton} 66a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 67a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdaltonvoid GLInstancedRendering::onBeginFlush(GrResourceProvider* rp) { 68a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton // Count what there is to draw. 69a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton BatchList::Iter iter; 70a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton iter.init(this->trackedBatches(), BatchList::Iter::kHead_IterStart); 71a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton int numGLInstances = 0; 72a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton int numGLDrawCmds = 0; 73a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton while (Batch* b = iter.get()) { 74a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GLBatch* batch = static_cast<GLBatch*>(b); 75a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton iter.next(); 76a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 77a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton numGLInstances += batch->fNumDraws; 78a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton numGLDrawCmds += batch->numGLCommands(); 79a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 80a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton if (!numGLDrawCmds) { 81a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton return; 82a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 83a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton SkASSERT(numGLInstances); 84a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 85a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton // Lazily create a vertex array object. 86a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton if (!fVertexArrayID) { 87a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(GenVertexArrays(1, &fVertexArrayID)); 88a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton if (!fVertexArrayID) { 89a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton return; 90a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 91a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton this->glGpu()->bindVertexArray(fVertexArrayID); 92a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 93a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton // Attach our index buffer to the vertex array. 94485a12003ab48b54965d6f7172f3183358919d8ecsmartdalton SkASSERT(!this->indexBuffer()->isCPUBacked()); 95a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 96a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton static_cast<const GrGLBuffer*>(this->indexBuffer())->bufferID())); 97a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 98a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton // Set up the non-instanced attribs. 99485a12003ab48b54965d6f7172f3183358919d8ecsmartdalton this->glGpu()->bindBuffer(kVertex_GrBufferType, this->vertexBuffer()); 100a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(EnableVertexAttribArray((int)Attrib::kShapeCoords)); 101a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(VertexAttribPointer((int)Attrib::kShapeCoords, 2, GR_GL_FLOAT, GR_GL_FALSE, 102a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton sizeof(ShapeVertex), (void*) offsetof(ShapeVertex, fX))); 103a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(EnableVertexAttribArray((int)Attrib::kVertexAttrs)); 104a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(VertexAttribIPointer((int)Attrib::kVertexAttrs, 1, GR_GL_INT, sizeof(ShapeVertex), 105a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton (void*) offsetof(ShapeVertex, fAttrs))); 106a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 107a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton SkASSERT(SK_InvalidUniqueID == fInstanceAttribsBufferUniqueId); 108a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 109a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 110a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton // Create and map instance and draw-indirect buffers. 111a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton SkASSERT(!fInstanceBuffer); 112485a12003ab48b54965d6f7172f3183358919d8ecsmartdalton fInstanceBuffer.reset( 113a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton rp->createBuffer(sizeof(Instance) * numGLInstances, kVertex_GrBufferType, 114485a12003ab48b54965d6f7172f3183358919d8ecsmartdalton kDynamic_GrAccessPattern, 115485a12003ab48b54965d6f7172f3183358919d8ecsmartdalton GrResourceProvider::kNoPendingIO_Flag | 116485a12003ab48b54965d6f7172f3183358919d8ecsmartdalton GrResourceProvider::kRequireGpuMemory_Flag)); 117a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton if (!fInstanceBuffer) { 118a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton return; 119a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 120a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 121a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton SkASSERT(!fDrawIndirectBuffer); 1224c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton if (this->glGpu()->glCaps().drawIndirectSupport()) { 1234c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton fDrawIndirectBuffer.reset( 1244c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton rp->createBuffer(sizeof(GrGLDrawElementsIndirectCommand) * numGLDrawCmds, 1254c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton kDrawIndirect_GrBufferType, kDynamic_GrAccessPattern, 1264c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton GrResourceProvider::kNoPendingIO_Flag | 1274c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton GrResourceProvider::kRequireGpuMemory_Flag)); 1284c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton if (!fDrawIndirectBuffer) { 1294c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton return; 1304c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton } 131a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 132a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 133a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton Instance* glMappedInstances = static_cast<Instance*>(fInstanceBuffer->map()); 1344c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton SkASSERT(glMappedInstances); 135a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton int glInstancesIdx = 0; 136a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 1374c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton GrGLDrawElementsIndirectCommand* glMappedCmds = nullptr; 138a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton int glDrawCmdsIdx = 0; 1394c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton if (fDrawIndirectBuffer) { 1404c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton glMappedCmds = static_cast<GrGLDrawElementsIndirectCommand*>(fDrawIndirectBuffer->map()); 1414c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton SkASSERT(glMappedCmds); 1424c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton } 143a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 144a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton bool baseInstanceSupport = this->glGpu()->glCaps().baseInstanceSupport(); 1454c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton SkASSERT(!baseInstanceSupport || fDrawIndirectBuffer); 146a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 1474c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton SkASSERT(!fGLDrawCmdsInfo); 148a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton if (GR_GL_LOG_INSTANCED_BATCHES || !baseInstanceSupport) { 149a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton fGLDrawCmdsInfo.reset(numGLDrawCmds); 150a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 151a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 152a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton // Generate the instance and draw-indirect buffer contents based on the tracked batches. 153a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton iter.init(this->trackedBatches(), BatchList::Iter::kHead_IterStart); 154a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton while (Batch* b = iter.get()) { 155a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GLBatch* batch = static_cast<GLBatch*>(b); 156a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton iter.next(); 157a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 158a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton batch->fEmulatedBaseInstance = baseInstanceSupport ? 0 : glInstancesIdx; 159a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton batch->fGLDrawCmdsIdx = glDrawCmdsIdx; 160a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 161a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton const Batch::Draw* draw = batch->fHeadDraw; 162a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton SkASSERT(draw); 163a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton do { 164a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton int instanceCount = 0; 165a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton IndexRange geometry = draw->fGeometry; 166a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton SkASSERT(!geometry.isEmpty()); 167a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 168a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton do { 169a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton glMappedInstances[glInstancesIdx + instanceCount++] = draw->fInstance; 170a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton draw = draw->fNext; 171a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } while (draw && draw->fGeometry == geometry); 172a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 1734c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton if (fDrawIndirectBuffer) { 1744c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton GrGLDrawElementsIndirectCommand& glCmd = glMappedCmds[glDrawCmdsIdx]; 1754c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton glCmd.fCount = geometry.fCount; 1764c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton glCmd.fInstanceCount = instanceCount; 1774c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton glCmd.fFirstIndex = geometry.fStart; 1784c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton glCmd.fBaseVertex = 0; 1794c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton glCmd.fBaseInstance = baseInstanceSupport ? glInstancesIdx : 0; 1804c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton } 181a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 182a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton if (GR_GL_LOG_INSTANCED_BATCHES || !baseInstanceSupport) { 1834c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton GLDrawCmdInfo& cmdInfo = fGLDrawCmdsInfo[glDrawCmdsIdx]; 1844c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton cmdInfo.fGeometry = geometry; 1854c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton cmdInfo.fInstanceCount = instanceCount; 186a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 187a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 188a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton glInstancesIdx += instanceCount; 189a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton ++glDrawCmdsIdx; 190a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } while (draw); 191a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 192a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 193a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton SkASSERT(glDrawCmdsIdx == numGLDrawCmds); 1944c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton if (fDrawIndirectBuffer) { 1954c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton fDrawIndirectBuffer->unmap(); 1964c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton } 197a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 198a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton SkASSERT(glInstancesIdx == numGLInstances); 199a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton fInstanceBuffer->unmap(); 200a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton} 201a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 202a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdaltonvoid GLInstancedRendering::onDraw(const GrPipeline& pipeline, const InstanceProcessor& instProc, 203a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton const Batch* baseBatch) { 2044c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton if (!fDrawIndirectBuffer && !fGLDrawCmdsInfo) { 205a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton return; // beginFlush was not successful. 206a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 207a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton if (!this->glGpu()->flushGLState(pipeline, instProc)) { 208a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton return; 209a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 210a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 2114c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton if (fDrawIndirectBuffer) { 2124c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton this->glGpu()->bindBuffer(kDrawIndirect_GrBufferType, fDrawIndirectBuffer.get()); 2134c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton } 214a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 215a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton const GrGLCaps& glCaps = this->glGpu()->glCaps(); 216a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton const GLBatch* batch = static_cast<const GLBatch*>(baseBatch); 217a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton int numCommands = batch->numGLCommands(); 218a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 219a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton#if GR_GL_LOG_INSTANCED_BATCHES 220a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton SkASSERT(fGLDrawCmdsInfo); 221a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton SkDebugf("Instanced batch: ["); 222a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton for (int i = 0; i < numCommands; ++i) { 223a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton int glCmdIdx = batch->fGLDrawCmdsIdx + i; 224a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton SkDebugf("%s%i * %s", (i ? ", " : ""), fGLDrawCmdsInfo[glCmdIdx].fInstanceCount, 225a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton InstanceProcessor::GetNameOfIndexRange(fGLDrawCmdsInfo[glCmdIdx].fGeometry)); 226a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 227a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton SkDebugf("]\n"); 228a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton#else 229a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton SkASSERT(SkToBool(fGLDrawCmdsInfo) == !glCaps.baseInstanceSupport()); 230a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton#endif 231a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 2324c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton if (numCommands > 1 && glCaps.multiDrawIndirectSupport() && glCaps.baseInstanceSupport()) { 2334c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton SkASSERT(fDrawIndirectBuffer); 234a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton int glCmdsIdx = batch->fGLDrawCmdsIdx; 235a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton this->flushInstanceAttribs(batch->fEmulatedBaseInstance); 236a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(MultiDrawElementsIndirect(GR_GL_TRIANGLES, GR_GL_UNSIGNED_BYTE, 237a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton (GrGLDrawElementsIndirectCommand*) nullptr + glCmdsIdx, 238a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton numCommands, 0)); 2394c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton return; 2404c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton } 2414c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton 2424c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton int emulatedBaseInstance = batch->fEmulatedBaseInstance; 2434c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton for (int i = 0; i < numCommands; ++i) { 2444c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton int glCmdIdx = batch->fGLDrawCmdsIdx + i; 2454c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton this->flushInstanceAttribs(emulatedBaseInstance); 2464c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton if (fDrawIndirectBuffer) { 2474c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton GL_CALL(DrawElementsIndirect(GR_GL_TRIANGLES, GR_GL_UNSIGNED_BYTE, 2484c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton (GrGLDrawElementsIndirectCommand*) nullptr + glCmdIdx)); 2494c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton } else { 25035b26a457100804b7a782cdff1132d2b65176c35mtklein const GLDrawCmdInfo& cmdInfo = fGLDrawCmdsInfo[glCmdIdx]; 2514c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton GL_CALL(DrawElementsInstanced(GR_GL_TRIANGLES, cmdInfo.fGeometry.fCount, 2524c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton GR_GL_UNSIGNED_BYTE, 2534c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton (GrGLubyte*) nullptr + cmdInfo.fGeometry.fStart, 2544c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton cmdInfo.fInstanceCount)); 2554c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton } 2564c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton if (!glCaps.baseInstanceSupport()) { 25735b26a457100804b7a782cdff1132d2b65176c35mtklein const GLDrawCmdInfo& cmdInfo = fGLDrawCmdsInfo[glCmdIdx]; 2584c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton emulatedBaseInstance += cmdInfo.fInstanceCount; 2594c18b62a004599d5a36ab7d772302dff2be91a3bcsmartdalton } 260a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 261a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton} 262a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 263a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdaltonvoid GLInstancedRendering::flushInstanceAttribs(int baseInstance) { 264a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton SkASSERT(fVertexArrayID); 265a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton this->glGpu()->bindVertexArray(fVertexArrayID); 266a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 267a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton SkASSERT(fInstanceBuffer); 2688abb370aca280516f4861c6c942ec453aad018farobertphillips if (fInstanceAttribsBufferUniqueId != fInstanceBuffer->uniqueID() || 269a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton fInstanceAttribsBaseInstance != baseInstance) { 270a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton Instance* offsetInBuffer = (Instance*) nullptr + baseInstance; 271a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 272a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton this->glGpu()->bindBuffer(kVertex_GrBufferType, fInstanceBuffer.get()); 273a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 274a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton // Info attrib. 275a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(EnableVertexAttribArray((int)Attrib::kInstanceInfo)); 276a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(VertexAttribIPointer((int)Attrib::kInstanceInfo, 1, GR_GL_UNSIGNED_INT, 277a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton sizeof(Instance), &offsetInBuffer->fInfo)); 278a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(VertexAttribDivisor((int)Attrib::kInstanceInfo, 1)); 279a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 280a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton // Shape matrix attrib. 281a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(EnableVertexAttribArray((int)Attrib::kShapeMatrixX)); 282a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(EnableVertexAttribArray((int)Attrib::kShapeMatrixY)); 283a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(VertexAttribPointer((int)Attrib::kShapeMatrixX, 3, GR_GL_FLOAT, GR_GL_FALSE, 284a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton sizeof(Instance), &offsetInBuffer->fShapeMatrix2x3[0])); 285a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(VertexAttribPointer((int)Attrib::kShapeMatrixY, 3, GR_GL_FLOAT, GR_GL_FALSE, 286a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton sizeof(Instance), &offsetInBuffer->fShapeMatrix2x3[3])); 287a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(VertexAttribDivisor((int)Attrib::kShapeMatrixX, 1)); 288a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(VertexAttribDivisor((int)Attrib::kShapeMatrixY, 1)); 289a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 290a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton // Color attrib. 291a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(EnableVertexAttribArray((int)Attrib::kColor)); 292a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(VertexAttribPointer((int)Attrib::kColor, 4, GR_GL_UNSIGNED_BYTE, GR_GL_TRUE, 293a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton sizeof(Instance), &offsetInBuffer->fColor)); 294a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(VertexAttribDivisor((int)Attrib::kColor, 1)); 295a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 296a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton // Local rect attrib. 297a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(EnableVertexAttribArray((int)Attrib::kLocalRect)); 298a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(VertexAttribPointer((int)Attrib::kLocalRect, 4, GR_GL_FLOAT, GR_GL_FALSE, 299a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton sizeof(Instance), &offsetInBuffer->fLocalRect)); 300a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(VertexAttribDivisor((int)Attrib::kLocalRect, 1)); 301a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 3028abb370aca280516f4861c6c942ec453aad018farobertphillips fInstanceAttribsBufferUniqueId = fInstanceBuffer->uniqueID(); 303a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton fInstanceAttribsBaseInstance = baseInstance; 304a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 305a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton} 306a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 307a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdaltonvoid GLInstancedRendering::onEndFlush() { 308a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton fInstanceBuffer.reset(); 309a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton fDrawIndirectBuffer.reset(); 310a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton fGLDrawCmdsInfo.reset(0); 311a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton} 312a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 313a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdaltonvoid GLInstancedRendering::onResetGpuResources(ResetType resetType) { 314a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton if (fVertexArrayID && ResetType::kDestroy == resetType) { 315a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton GL_CALL(DeleteVertexArrays(1, &fVertexArrayID)); 316a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton this->glGpu()->notifyVertexArrayDelete(fVertexArrayID); 317a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton } 318a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton fVertexArrayID = 0; 319a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton fInstanceBuffer.reset(); 320a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton fDrawIndirectBuffer.reset(); 321a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton fInstanceAttribsBufferUniqueId = SK_InvalidUniqueID; 322a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton} 323a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton 324a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton} 325