blob: a8b9530228fe4a975e3a837580dc073e974b7984 [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
Brian Salomon89527432016-12-16 09:52:16 -050011#include "../private/GrInstancedPipelineInfo.h"
Greg Daniel77b53f62016-10-18 11:48:51 -040012#include "GrGpu.h"
csmartdaltona7f29642016-07-07 08:49:11 -070013#include "GrMemoryPool.h"
14#include "SkTInternalLList.h"
csmartdaltona7f29642016-07-07 08:49:11 -070015#include "instanced/InstancedRenderingTypes.h"
Brian Salomon89527432016-12-16 09:52:16 -050016#include "ops/GrDrawOp.h"
csmartdaltona7f29642016-07-07 08:49:11 -070017
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
Brian Salomon89527432016-12-16 09:52:16 -050026 * 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.
csmartdaltona7f29642016-07-07 08:49:11 -070028 *
29 * During a flush, this class assembles the accumulated draw data into a single vertex and texel
Brian Salomon99ad1642016-12-16 09:50:45 -050030 * buffer, and its subclass draws the ops using backend-specific instanced rendering APIs.
csmartdaltona7f29642016-07-07 08:49:11 -070031 *
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 /**
Brian Salomon99ad1642016-12-16 09:50:45 -050042 * 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
csmartdaltona7f29642016-07-07 08:49:11 -070044 * rather relies on this class to handle the rendering. The client must call beginFlush() on
Brian Salomon99ad1642016-12-16 09:50:45 -050045 * this class before attempting to flush ops returned by it. It is invalid to record new
csmartdaltona7f29642016-07-07 08:49:11 -070046 * draws between beginFlush() and endFlush().
47 */
Brian Salomonf8334782017-01-03 09:42:58 -050048 std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordRect(const SkRect&, const SkMatrix&,
Brian Salomon54d212e2017-03-21 14:22:38 -040049 GrPaint&&, GrAA,
50 const GrInstancedPipelineInfo&);
csmartdaltona7f29642016-07-07 08:49:11 -070051
Brian Salomonf8334782017-01-03 09:42:58 -050052 std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordRect(const SkRect&, const SkMatrix&,
Brian Salomon54d212e2017-03-21 14:22:38 -040053 GrPaint&&, const SkRect& localRect,
54 GrAA,
55 const GrInstancedPipelineInfo&);
csmartdaltona7f29642016-07-07 08:49:11 -070056
Brian Salomonf8334782017-01-03 09:42:58 -050057 std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordRect(const SkRect&, const SkMatrix&,
Brian Salomon54d212e2017-03-21 14:22:38 -040058 GrPaint&&,
59 const SkMatrix& localMatrix, GrAA,
60 const GrInstancedPipelineInfo&);
csmartdaltona7f29642016-07-07 08:49:11 -070061
Brian Salomonf8334782017-01-03 09:42:58 -050062 std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordOval(const SkRect&, const SkMatrix&,
Brian Salomon54d212e2017-03-21 14:22:38 -040063 GrPaint&&, GrAA,
64 const GrInstancedPipelineInfo&);
csmartdaltona7f29642016-07-07 08:49:11 -070065
Brian Salomonf8334782017-01-03 09:42:58 -050066 std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordRRect(const SkRRect&, const SkMatrix&,
Brian Salomon54d212e2017-03-21 14:22:38 -040067 GrPaint&&, GrAA,
68 const GrInstancedPipelineInfo&);
csmartdaltona7f29642016-07-07 08:49:11 -070069
Brian Salomonf8334782017-01-03 09:42:58 -050070 std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordDRRect(const SkRRect& outer,
71 const SkRRect& inner,
Brian Salomon54d212e2017-03-21 14:22:38 -040072 const SkMatrix&, GrPaint&&, GrAA,
73 const GrInstancedPipelineInfo&);
csmartdaltona7f29642016-07-07 08:49:11 -070074
75 /**
76 * Compiles all recorded draws into GPU buffers and allows the client to begin flushing the
Brian Salomon99ad1642016-12-16 09:50:45 -050077 * ops created by this class.
csmartdaltona7f29642016-07-07 08:49:11 -070078 */
79 void beginFlush(GrResourceProvider*);
80
81 /**
Brian Salomon99ad1642016-12-16 09:50:45 -050082 * Called once the ops created previously by this class have all been released. Allows the
csmartdaltona7f29642016-07-07 08:49:11 -070083 * 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
98protected:
Brian Salomon99ad1642016-12-16 09:50:45 -050099 class Op : public GrDrawOp {
csmartdaltona7f29642016-07-07 08:49:11 -0700100 public:
Brian Salomon99ad1642016-12-16 09:50:45 -0500101 SK_DECLARE_INTERNAL_LLIST_INTERFACE(Op);
csmartdaltona7f29642016-07-07 08:49:11 -0700102
Brian Salomon99ad1642016-12-16 09:50:45 -0500103 ~Op() override;
104 const char* name() const override { return "InstancedRendering::Op"; }
csmartdaltona7f29642016-07-07 08:49:11 -0700105
Brian Salomon7c3e7182016-12-01 09:35:30 -0500106 SkString dumpInfo() const override {
107 SkString string;
Brian Salomonaf9847e2017-03-01 11:28:27 -0500108 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 (unsigned)fInfo.fAAType,
113 fInfo.fShapeTypes,
114 fInfo.fInnerShapeTypes,
115 fInfo.fHasPerspective,
116 fInfo.fNonSquare,
117 fPixelLoad,
118 fIsTracked,
119 fNumDraws,
120 fNumChangesInGeometry);
Brian Salomon7c3e7182016-12-01 09:35:30 -0500121 string.append(INHERITED::dumpInfo());
122 return string;
123 }
124
csmartdaltona7f29642016-07-07 08:49:11 -0700125 struct Draw {
126 Instance fInstance;
127 IndexRange fGeometry;
128 Draw* fNext;
129 };
130
131 Draw& getSingleDraw() const { SkASSERT(fHeadDraw && !fHeadDraw->fNext); return *fHeadDraw; }
132 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);
Brian Salomon54d212e2017-03-21 14:22:38 -0400138 FixedFunctionFlags fixedFunctionFlags() const override {
139 return GrAATypeIsHW(fInfo.aaType()) ? FixedFunctionFlags::kUsesHWAA
140 : FixedFunctionFlags::kNone;
141 }
142 bool xpRequiresDstTexture(const GrCaps&, const GrAppliedClip*) override;
csmartdaltona7f29642016-07-07 08:49:11 -0700143
Brian Salomond543e0a2017-03-06 16:36:49 -0500144 // Registers the op with the InstancedRendering list of tracked ops.
145 void wasRecorded() override;
146
csmartdaltona7f29642016-07-07 08:49:11 -0700147 protected:
Brian Salomon54d212e2017-03-21 14:22:38 -0400148 Op(uint32_t classID, GrPaint&&, InstancedRendering*);
csmartdaltona7f29642016-07-07 08:49:11 -0700149
Brian Salomon99ad1642016-12-16 09:50:45 -0500150 InstancedRendering* const fInstancedRendering;
151 OpInfo fInfo;
152 SkScalar fPixelLoad;
Brian Salomon54d212e2017-03-21 14:22:38 -0400153 GrProcessorSet fProcessors;
Brian Salomon99ad1642016-12-16 09:50:45 -0500154 SkSTArray<5, ParamsTexel, true> fParams;
Brian Salomon4fc77402017-03-30 16:48:26 -0400155 bool fIsTracked : 1;
156 bool fRequiresBarrierOnOverlap : 1;
Brian Salomon99ad1642016-12-16 09:50:45 -0500157 int fNumDraws;
158 int fNumChangesInGeometry;
159 Draw* fHeadDraw;
160 Draw* fTailDraw;
csmartdaltona7f29642016-07-07 08:49:11 -0700161
Brian Salomon92aee3d2016-12-21 09:20:25 -0500162 private:
Brian Salomon92aee3d2016-12-21 09:20:25 -0500163 bool onCombineIfPossible(GrOp* other, const GrCaps& caps) override;
164 void onPrepare(GrOpFlushState*) override {}
Brian Salomon9e50f7b2017-03-06 12:02:34 -0500165 void onExecute(GrOpFlushState*) override;
Brian Salomon92aee3d2016-12-21 09:20:25 -0500166
Brian Salomon9afd3712016-12-01 10:59:09 -0500167 typedef GrDrawOp INHERITED;
csmartdaltona7f29642016-07-07 08:49:11 -0700168
169 friend class InstancedRendering;
170 };
171
Brian Salomon99ad1642016-12-16 09:50:45 -0500172 typedef SkTInternalLList<Op> OpList;
csmartdaltona7f29642016-07-07 08:49:11 -0700173
csmartdaltone0d36292016-07-29 08:14:20 -0700174 InstancedRendering(GrGpu* gpu);
csmartdaltona7f29642016-07-07 08:49:11 -0700175
Brian Salomon99ad1642016-12-16 09:50:45 -0500176 const OpList& trackedOps() const { return fTrackedOps; }
Hal Canary144caf52016-11-07 17:57:18 -0500177 const GrBuffer* vertexBuffer() const { SkASSERT(fVertexBuffer); return fVertexBuffer.get(); }
178 const GrBuffer* indexBuffer() const { SkASSERT(fIndexBuffer); return fIndexBuffer.get(); }
csmartdaltona7f29642016-07-07 08:49:11 -0700179
180 virtual void onBeginFlush(GrResourceProvider*) = 0;
Brian Salomon99ad1642016-12-16 09:50:45 -0500181 virtual void onDraw(const GrPipeline&, const InstanceProcessor&, const Op*) = 0;
csmartdaltona7f29642016-07-07 08:49:11 -0700182 virtual void onEndFlush() = 0;
183 virtual void onResetGpuResources(ResetType) = 0;
184
185private:
186 enum class State : bool {
187 kRecordingDraws,
188 kFlushing
189 };
190
Brian Salomonf8334782017-01-03 09:42:58 -0500191 std::unique_ptr<Op> SK_WARN_UNUSED_RESULT recordShape(ShapeType, const SkRect& bounds,
Brian Salomon54d212e2017-03-21 14:22:38 -0400192 const SkMatrix& viewMatrix, GrPaint&&,
Brian Salomonf8334782017-01-03 09:42:58 -0500193 const SkRect& localRect, GrAA aa,
Brian Salomon54d212e2017-03-21 14:22:38 -0400194 const GrInstancedPipelineInfo&);
csmartdaltona7f29642016-07-07 08:49:11 -0700195
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500196 bool selectAntialiasMode(const SkMatrix& viewMatrix, GrAA aa, const GrInstancedPipelineInfo&,
Brian Salomonaf9847e2017-03-01 11:28:27 -0500197 GrAAType*);
csmartdaltona7f29642016-07-07 08:49:11 -0700198
Brian Salomon54d212e2017-03-21 14:22:38 -0400199 virtual std::unique_ptr<Op> makeOp(GrPaint&&) = 0;
csmartdaltona7f29642016-07-07 08:49:11 -0700200
Brian Salomon99ad1642016-12-16 09:50:45 -0500201 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;
csmartdaltona7f29642016-07-07 08:49:11 -0700209};
210
211}
212
213#endif