aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/instanced/InstancedRendering.h
blob: e349f6337b0182234b27aef8edb911924b724301 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef gr_instanced_InstancedRendering_DEFINED
#define gr_instanced_InstancedRendering_DEFINED

#include "instanced/InstancedOp.h"
#include "instanced/InstancedRenderingTypes.h"

#include "SkTInternalLList.h"

class GrGpu;
class GrResourceProvider;

namespace gr_instanced {

class InstancedOp;
class InstanceProcessor;


/**
 * Instanced Rendering occurs through the interaction of four class:
 *   InstancedOp
 *   OpAllocator
 *   InstancedRendering
 *   InstanceProcessor
 *
 * The InstancedOp is a GrDrawOp but is more of a proxy than normal operations. It accumulates a
 * LL of Draw objects that are allocated all together by the OpAllocator.
 *
 * There is only one OpAllocator which encapsulates the creation of InstancedOps and the pool
 * of memory used for their Draw objects.
 *
 * The InstancedRendering class tracks a list of InstancedOps that will all be drawn during 
 * the same flush. There is currently one per opList. The nature of instanced
 * rendering allows these ops to combine well and render efficiently.
 * During a flush, it assembles the accumulated draw data into a single vertex and texel
 * buffer per opList, and its subclasses draw the ops using backend-specific instanced
 * rendering APIs.
 *
 * InstanceProcessors implement the shaders required for instance rendering.
 */
class InstancedRendering : public SkNoncopyable {
public:
    virtual ~InstancedRendering();

    GrGpu* gpu() const { return fGpu.get(); }

    /**
     * Compiles all recorded draws into GPU buffers and allows the client to begin flushing the
     * ops created by this class.
     */
    void beginFlush(GrResourceProvider*);

    void draw(const GrPipeline& pipeline, OpInfo info, const InstancedOp* baseOp);

    /**
     * Called once the ops created previously by this class have all been released. Allows the
     * client to begin recording draws again.
     */
    void endFlush();

    enum class ResetType : bool {
        kDestroy,
        kAbandon
    };

    /**
     * Resets all GPU resources, including those that are held long term. They will be lazily
     * reinitialized if the class begins to be used again.
     */
    void resetGpuResources(ResetType);

    void addOp(InstancedOp* op) { fTrackedOps.addToTail(op); }
    void removeOp(InstancedOp* op) { fTrackedOps.remove(op); }
    int addOpParams(InstancedOp* op);

#ifdef SK_DEBUG
    bool isFlushing() const { return InstancedRendering::State::kFlushing == fState; }
#endif

protected:
    typedef SkTInternalLList<InstancedOp> OpList;

    InstancedRendering(GrGpu* gpu);

    const OpList& trackedOps() const { return fTrackedOps; }
    const GrBuffer* vertexBuffer() const { SkASSERT(fVertexBuffer); return fVertexBuffer.get(); }
    const GrBuffer* indexBuffer() const { SkASSERT(fIndexBuffer); return fIndexBuffer.get(); }

    virtual void onBeginFlush(GrResourceProvider*) = 0;
    virtual void onDraw(const GrPipeline&, const InstanceProcessor&, const InstancedOp*) = 0;
    virtual void onEndFlush() = 0;
    virtual void onResetGpuResources(ResetType) = 0;

private:
#ifdef SK_DEBUG
    enum class State : bool {
        kRecordingDraws,
        kFlushing
    };
#endif

    const sk_sp<GrGpu> fGpu;
    SkDEBUGCODE(State fState;)
    SkSTArray<1024, ParamsTexel, true> fParams;
    OpList fTrackedOps;
    sk_sp<const GrBuffer> fVertexBuffer;
    sk_sp<const GrBuffer> fIndexBuffer;
    sk_sp<GrBuffer> fParamsBuffer;
};

}

#endif