blob: d3a01523a68dc6cc4f3d57ca14d5ee06bd9ec9e2 [file] [log] [blame]
csmartdaltona7f29642016-07-07 08:49:11 -07001/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef gr_instanced_InstancedRendering_DEFINED
9#define gr_instanced_InstancedRendering_DEFINED
10
Greg Daniel77b53f62016-10-18 11:48:51 -040011#include "GrGpu.h"
csmartdaltona7f29642016-07-07 08:49:11 -070012#include "GrMemoryPool.h"
13#include "SkTInternalLList.h"
Brian Salomon9afd3712016-12-01 10:59:09 -050014#include "batches/GrDrawOp.h"
csmartdaltona7f29642016-07-07 08:49:11 -070015#include "instanced/InstancedRenderingTypes.h"
16#include "../private/GrInstancedPipelineInfo.h"
17
18class GrResourceProvider;
19
20namespace gr_instanced {
21
22class InstanceProcessor;
23
24/**
25 * This class serves as a centralized clearinghouse for instanced rendering. It accumulates data for
26 * instanced draws into one location, and creates special batches that pull from this data. The
27 * nature of instanced rendering allows these batches to combine well and render efficiently.
28 *
29 * During a flush, this class assembles the accumulated draw data into a single vertex and texel
30 * buffer, and its subclass draws the batches using backend-specific instanced rendering APIs.
31 *
32 * This class is responsible for the CPU side of instanced rendering. Shaders are implemented by
33 * InstanceProcessor.
34 */
35class InstancedRendering : public SkNoncopyable {
36public:
37 virtual ~InstancedRendering() { SkASSERT(State::kRecordingDraws == fState); }
38
Hal Canary144caf52016-11-07 17:57:18 -050039 GrGpu* gpu() const { return fGpu.get(); }
csmartdaltona7f29642016-07-07 08:49:11 -070040
41 /**
42 * These methods make a new record internally for an instanced draw, and return a batch that is
43 * effectively just an index to that record. The returned batch is not self-contained, but
44 * rather relies on this class to handle the rendering. The client must call beginFlush() on
45 * this class before attempting to flush batches returned by it. It is invalid to record new
46 * draws between beginFlush() and endFlush().
47 */
Brian Salomon9afd3712016-12-01 10:59:09 -050048 GrDrawOp* SK_WARN_UNUSED_RESULT recordRect(const SkRect&, const SkMatrix&, GrColor,
Brian Salomon073285c2016-12-09 20:02:08 +000049 bool antialias, const GrInstancedPipelineInfo&,
50 bool* useHWAA);
csmartdaltona7f29642016-07-07 08:49:11 -070051
Brian Salomon9afd3712016-12-01 10:59:09 -050052 GrDrawOp* SK_WARN_UNUSED_RESULT recordRect(const SkRect&, const SkMatrix&, GrColor,
Brian Salomon073285c2016-12-09 20:02:08 +000053 const SkRect& localRect, bool antialias,
54 const GrInstancedPipelineInfo&, bool* useHWAA);
csmartdaltona7f29642016-07-07 08:49:11 -070055
Brian Salomon9afd3712016-12-01 10:59:09 -050056 GrDrawOp* SK_WARN_UNUSED_RESULT recordRect(const SkRect&, const SkMatrix&, GrColor,
Brian Salomon073285c2016-12-09 20:02:08 +000057 const SkMatrix& localMatrix, bool antialias,
58 const GrInstancedPipelineInfo&, bool* useHWAA);
csmartdaltona7f29642016-07-07 08:49:11 -070059
Brian Salomon9afd3712016-12-01 10:59:09 -050060 GrDrawOp* SK_WARN_UNUSED_RESULT recordOval(const SkRect&, const SkMatrix&, GrColor,
Brian Salomon073285c2016-12-09 20:02:08 +000061 bool antialias, const GrInstancedPipelineInfo&,
62 bool* useHWAA);
csmartdaltona7f29642016-07-07 08:49:11 -070063
Brian Salomon9afd3712016-12-01 10:59:09 -050064 GrDrawOp* SK_WARN_UNUSED_RESULT recordRRect(const SkRRect&, const SkMatrix&, GrColor,
Brian Salomon073285c2016-12-09 20:02:08 +000065 bool antialias, const GrInstancedPipelineInfo&,
66 bool* useHWAA);
csmartdaltona7f29642016-07-07 08:49:11 -070067
Brian Salomon9afd3712016-12-01 10:59:09 -050068 GrDrawOp* SK_WARN_UNUSED_RESULT recordDRRect(const SkRRect& outer, const SkRRect& inner,
Brian Salomon073285c2016-12-09 20:02:08 +000069 const SkMatrix&, GrColor, bool antialias,
70 const GrInstancedPipelineInfo&, bool* useHWAA);
csmartdaltona7f29642016-07-07 08:49:11 -070071
72 /**
73 * Compiles all recorded draws into GPU buffers and allows the client to begin flushing the
74 * batches created by this class.
75 */
76 void beginFlush(GrResourceProvider*);
77
78 /**
79 * Called once the batches created previously by this class have all been released. Allows the
80 * client to begin recording draws again.
81 */
82 void endFlush();
83
84 enum class ResetType : bool {
85 kDestroy,
86 kAbandon
87 };
88
89 /**
90 * Resets all GPU resources, including those that are held long term. They will be lazily
91 * reinitialized if the class begins to be used again.
92 */
93 void resetGpuResources(ResetType);
94
95protected:
Brian Salomon9afd3712016-12-01 10:59:09 -050096 class Batch : public GrDrawOp {
csmartdaltona7f29642016-07-07 08:49:11 -070097 public:
98 SK_DECLARE_INTERNAL_LLIST_INTERFACE(Batch);
99
100 ~Batch() override;
101 const char* name() const override { return "Instanced Batch"; }
102
Brian Salomon7c3e7182016-12-01 09:35:30 -0500103 SkString dumpInfo() const override {
104 SkString string;
105 string.printf("AA: %d, ShapeTypes: 0x%02x, IShapeTypes: 0x%02x, Persp %d, "
106 "NonSquare: %d, PLoad: %0.2f, Tracked: %d, NumDraws: %d, "
107 "GeomChanges: %d\n",
108 (int)fInfo.fAntialiasMode,
109 fInfo.fShapeTypes,
110 fInfo.fInnerShapeTypes,
111 fInfo.fHasPerspective,
112 fInfo.fNonSquare,
113 fPixelLoad,
114 fIsTracked,
115 fNumDraws,
116 fNumChangesInGeometry);
117 string.append(DumpPipelineInfo(*this->pipeline()));
118 string.append(INHERITED::dumpInfo());
119 return string;
120 }
121
csmartdaltona7f29642016-07-07 08:49:11 -0700122 struct Draw {
123 Instance fInstance;
124 IndexRange fGeometry;
125 Draw* fNext;
126 };
127
128 Draw& getSingleDraw() const { SkASSERT(fHeadDraw && !fHeadDraw->fNext); return *fHeadDraw; }
129 Instance& getSingleInstance() const { return this->getSingleDraw().fInstance; }
130
131 void appendRRectParams(const SkRRect&);
132 void appendParamsTexel(const SkScalar* vals, int count);
133 void appendParamsTexel(SkScalar x, SkScalar y, SkScalar z, SkScalar w);
134 void appendParamsTexel(SkScalar x, SkScalar y, SkScalar z);
135
136 protected:
137 Batch(uint32_t classID, InstancedRendering* ir);
138
139 void initBatchTracker(const GrXPOverridesForBatch&) override;
Brian Salomon25a88092016-12-01 09:36:50 -0500140 bool onCombineIfPossible(GrOp* other, const GrCaps& caps) override;
csmartdaltona7f29642016-07-07 08:49:11 -0700141
142 void computePipelineOptimizations(GrInitInvariantOutput* color,
143 GrInitInvariantOutput* coverage,
144 GrBatchToXPOverrides*) const override;
145
Brian Salomon742e31d2016-12-07 17:06:19 -0500146 void onPrepare(GrOpFlushState*) override {}
147 void onDraw(GrOpFlushState*, const SkRect& bounds) override;
csmartdaltona7f29642016-07-07 08:49:11 -0700148
149 InstancedRendering* const fInstancedRendering;
150 BatchInfo fInfo;
151 SkScalar fPixelLoad;
152 SkSTArray<5, ParamsTexel, true> fParams;
153 bool fIsTracked;
154 int fNumDraws;
155 int fNumChangesInGeometry;
156 Draw* fHeadDraw;
157 Draw* fTailDraw;
158
Brian Salomon9afd3712016-12-01 10:59:09 -0500159 typedef GrDrawOp INHERITED;
csmartdaltona7f29642016-07-07 08:49:11 -0700160
161 friend class InstancedRendering;
162 };
163
164 typedef SkTInternalLList<Batch> BatchList;
165
csmartdaltone0d36292016-07-29 08:14:20 -0700166 InstancedRendering(GrGpu* gpu);
csmartdaltona7f29642016-07-07 08:49:11 -0700167
168 const BatchList& trackedBatches() const { return fTrackedBatches; }
Hal Canary144caf52016-11-07 17:57:18 -0500169 const GrBuffer* vertexBuffer() const { SkASSERT(fVertexBuffer); return fVertexBuffer.get(); }
170 const GrBuffer* indexBuffer() const { SkASSERT(fIndexBuffer); return fIndexBuffer.get(); }
csmartdaltona7f29642016-07-07 08:49:11 -0700171
172 virtual void onBeginFlush(GrResourceProvider*) = 0;
173 virtual void onDraw(const GrPipeline&, const InstanceProcessor&, const Batch*) = 0;
174 virtual void onEndFlush() = 0;
175 virtual void onResetGpuResources(ResetType) = 0;
176
177private:
178 enum class State : bool {
179 kRecordingDraws,
180 kFlushing
181 };
182
183 Batch* SK_WARN_UNUSED_RESULT recordShape(ShapeType, const SkRect& bounds,
184 const SkMatrix& viewMatrix, GrColor,
Brian Salomon073285c2016-12-09 20:02:08 +0000185 const SkRect& localRect, bool antialias,
186 const GrInstancedPipelineInfo&, bool* requireHWAA);
csmartdaltona7f29642016-07-07 08:49:11 -0700187
Brian Salomon073285c2016-12-09 20:02:08 +0000188 bool selectAntialiasMode(const SkMatrix& viewMatrix, bool antialias,
189 const GrInstancedPipelineInfo&, bool* useHWAA, AntialiasMode*);
csmartdaltona7f29642016-07-07 08:49:11 -0700190
191 virtual Batch* createBatch() = 0;
192
Hal Canary144caf52016-11-07 17:57:18 -0500193 const sk_sp<GrGpu> fGpu;
csmartdaltona7f29642016-07-07 08:49:11 -0700194 State fState;
dskibae4cd0062016-11-29 06:50:35 -0800195 GrObjectMemoryPool<Batch::Draw> fDrawPool;
csmartdaltona7f29642016-07-07 08:49:11 -0700196 SkSTArray<1024, ParamsTexel, true> fParams;
197 BatchList fTrackedBatches;
Hal Canary144caf52016-11-07 17:57:18 -0500198 sk_sp<const GrBuffer> fVertexBuffer;
199 sk_sp<const GrBuffer> fIndexBuffer;
200 sk_sp<GrBuffer> fParamsBuffer;
csmartdaltona7f29642016-07-07 08:49:11 -0700201};
202
203}
204
205#endif