GLInstancedRendering.cpp revision 25a880960a9a689a745a01071ecba3fe494b5940
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:
2025a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    DEFINE_OP_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    }
411edc5b92fecefb79f01cf0e302646eacf32b06c7Brian Salomon    return InstanceProcessor::CheckSupport(*glCaps.shaderCaps(), 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
107294870ff119b89fc902773643b054f14e5d1f554Robert Phillips        SkASSERT(fInstanceAttribsBufferUniqueId.isInvalid());
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    }
2072eda5b3a65f54105ae3776160373eed5500c515fbsalomon    if (!this->glGpu()->flushGLState(pipeline, instProc, false)) {
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();
321294870ff119b89fc902773643b054f14e5d1f554Robert Phillips    fInstanceAttribsBufferUniqueId.makeInvalid();
322a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton}
323a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton
324a7f29640f6ab4eb50962a9d9f12d01ac2ce8b471csmartdalton}
325