Line data Source code
1 : /*
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 :
11 : #include "../private/GrInstancedPipelineInfo.h"
12 : #include "GrGpu.h"
13 : #include "GrMemoryPool.h"
14 : #include "SkTInternalLList.h"
15 : #include "instanced/InstancedRenderingTypes.h"
16 : #include "ops/GrDrawOp.h"
17 :
18 : class GrResourceProvider;
19 :
20 : namespace gr_instanced {
21 :
22 : class 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 ops that pull from this data. The
27 : * nature of instanced rendering allows these ops 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 ops 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 : */
35 : class InstancedRendering : public SkNoncopyable {
36 : public:
37 0 : virtual ~InstancedRendering() { SkASSERT(State::kRecordingDraws == fState); }
38 :
39 0 : GrGpu* gpu() const { return fGpu.get(); }
40 :
41 : /**
42 : * These methods make a new record internally for an instanced draw, and return an op that is
43 : * effectively just an index to that record. The returned op 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 ops returned by it. It is invalid to record new
46 : * draws between beginFlush() and endFlush().
47 : */
48 : std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordRect(const SkRect&, const SkMatrix&,
49 : GrPaint&&, GrAA,
50 : const GrInstancedPipelineInfo&);
51 :
52 : std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordRect(const SkRect&, const SkMatrix&,
53 : GrPaint&&, const SkRect& localRect,
54 : GrAA,
55 : const GrInstancedPipelineInfo&);
56 :
57 : std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordRect(const SkRect&, const SkMatrix&,
58 : GrPaint&&,
59 : const SkMatrix& localMatrix, GrAA,
60 : const GrInstancedPipelineInfo&);
61 :
62 : std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordOval(const SkRect&, const SkMatrix&,
63 : GrPaint&&, GrAA,
64 : const GrInstancedPipelineInfo&);
65 :
66 : std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordRRect(const SkRRect&, const SkMatrix&,
67 : GrPaint&&, GrAA,
68 : const GrInstancedPipelineInfo&);
69 :
70 : std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordDRRect(const SkRRect& outer,
71 : const SkRRect& inner,
72 : const SkMatrix&, GrPaint&&, GrAA,
73 : const GrInstancedPipelineInfo&);
74 :
75 : /**
76 : * Compiles all recorded draws into GPU buffers and allows the client to begin flushing the
77 : * ops created by this class.
78 : */
79 : void beginFlush(GrResourceProvider*);
80 :
81 : /**
82 : * Called once the ops created previously by this class have all been released. Allows the
83 : * client to begin recording draws again.
84 : */
85 : void endFlush();
86 :
87 : enum class ResetType : bool {
88 : kDestroy,
89 : kAbandon
90 : };
91 :
92 : /**
93 : * Resets all GPU resources, including those that are held long term. They will be lazily
94 : * reinitialized if the class begins to be used again.
95 : */
96 : void resetGpuResources(ResetType);
97 :
98 : protected:
99 : class Op : public GrDrawOp {
100 : public:
101 : SK_DECLARE_INTERNAL_LLIST_INTERFACE(Op);
102 :
103 : ~Op() override;
104 0 : const char* name() const override { return "InstancedRendering::Op"; }
105 :
106 0 : SkString dumpInfo() const override {
107 0 : SkString string;
108 0 : string.printf(
109 : "AA: %d, ShapeTypes: 0x%02x, IShapeTypes: 0x%02x, Persp %d, "
110 : "NonSquare: %d, PLoad: %0.2f, Tracked: %d, NumDraws: %d, "
111 : "GeomChanges: %d\n",
112 0 : (unsigned)fInfo.fAAType,
113 0 : fInfo.fShapeTypes,
114 0 : fInfo.fInnerShapeTypes,
115 0 : fInfo.fHasPerspective,
116 0 : fInfo.fNonSquare,
117 0 : fPixelLoad,
118 0 : fIsTracked,
119 0 : fNumDraws,
120 0 : fNumChangesInGeometry);
121 0 : string.append(INHERITED::dumpInfo());
122 0 : return string;
123 : }
124 :
125 : struct Draw {
126 : Instance fInstance;
127 : IndexRange fGeometry;
128 : Draw* fNext;
129 : };
130 :
131 0 : Draw& getSingleDraw() const { SkASSERT(fHeadDraw && !fHeadDraw->fNext); return *fHeadDraw; }
132 0 : Instance& getSingleInstance() const { return this->getSingleDraw().fInstance; }
133 :
134 : void appendRRectParams(const SkRRect&);
135 : void appendParamsTexel(const SkScalar* vals, int count);
136 : void appendParamsTexel(SkScalar x, SkScalar y, SkScalar z, SkScalar w);
137 : void appendParamsTexel(SkScalar x, SkScalar y, SkScalar z);
138 0 : FixedFunctionFlags fixedFunctionFlags() const override {
139 0 : return GrAATypeIsHW(fInfo.aaType()) ? FixedFunctionFlags::kUsesHWAA
140 0 : : FixedFunctionFlags::kNone;
141 : }
142 : bool xpRequiresDstTexture(const GrCaps&, const GrAppliedClip*) override;
143 :
144 : // Registers the op with the InstancedRendering list of tracked ops.
145 : void wasRecorded() override;
146 :
147 : protected:
148 : Op(uint32_t classID, GrPaint&&, InstancedRendering*);
149 :
150 : InstancedRendering* const fInstancedRendering;
151 : OpInfo fInfo;
152 : SkScalar fPixelLoad;
153 : GrProcessorSet fProcessors;
154 : SkSTArray<5, ParamsTexel, true> fParams;
155 : bool fIsTracked : 1;
156 : bool fRequiresBarrierOnOverlap : 1;
157 : int fNumDraws;
158 : int fNumChangesInGeometry;
159 : Draw* fHeadDraw;
160 : Draw* fTailDraw;
161 :
162 : private:
163 : bool onCombineIfPossible(GrOp* other, const GrCaps& caps) override;
164 0 : void onPrepare(GrOpFlushState*) override {}
165 : void onExecute(GrOpFlushState*) override;
166 :
167 : typedef GrDrawOp INHERITED;
168 :
169 : friend class InstancedRendering;
170 : };
171 :
172 : typedef SkTInternalLList<Op> OpList;
173 :
174 : InstancedRendering(GrGpu* gpu);
175 :
176 0 : const OpList& trackedOps() const { return fTrackedOps; }
177 0 : const GrBuffer* vertexBuffer() const { SkASSERT(fVertexBuffer); return fVertexBuffer.get(); }
178 0 : const GrBuffer* indexBuffer() const { SkASSERT(fIndexBuffer); return fIndexBuffer.get(); }
179 :
180 : virtual void onBeginFlush(GrResourceProvider*) = 0;
181 : virtual void onDraw(const GrPipeline&, const InstanceProcessor&, const Op*) = 0;
182 : virtual void onEndFlush() = 0;
183 : virtual void onResetGpuResources(ResetType) = 0;
184 :
185 : private:
186 : enum class State : bool {
187 : kRecordingDraws,
188 : kFlushing
189 : };
190 :
191 : std::unique_ptr<Op> SK_WARN_UNUSED_RESULT recordShape(ShapeType, const SkRect& bounds,
192 : const SkMatrix& viewMatrix, GrPaint&&,
193 : const SkRect& localRect, GrAA aa,
194 : const GrInstancedPipelineInfo&);
195 :
196 : bool selectAntialiasMode(const SkMatrix& viewMatrix, GrAA aa, const GrInstancedPipelineInfo&,
197 : GrAAType*);
198 :
199 : virtual std::unique_ptr<Op> makeOp(GrPaint&&) = 0;
200 :
201 : const sk_sp<GrGpu> fGpu;
202 : State fState;
203 : GrObjectMemoryPool<Op::Draw> fDrawPool;
204 : SkSTArray<1024, ParamsTexel, true> fParams;
205 : OpList fTrackedOps;
206 : sk_sp<const GrBuffer> fVertexBuffer;
207 : sk_sp<const GrBuffer> fIndexBuffer;
208 : sk_sp<GrBuffer> fParamsBuffer;
209 : };
210 :
211 : }
212 :
213 : #endif
|