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