blob: 03120d21d5806b8bd73a425dfa4fbb4cf43e3105 [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&,
49 GrColor, GrAA,
50 const GrInstancedPipelineInfo&,
51 GrAAType*);
csmartdaltona7f29642016-07-07 08:49:11 -070052
Brian Salomonf8334782017-01-03 09:42:58 -050053 std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordRect(const SkRect&, const SkMatrix&,
54 GrColor, const SkRect& localRect,
55 GrAA, const GrInstancedPipelineInfo&,
56 GrAAType*);
csmartdaltona7f29642016-07-07 08:49:11 -070057
Brian Salomonf8334782017-01-03 09:42:58 -050058 std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordRect(const SkRect&, const SkMatrix&,
59 GrColor, const SkMatrix& localMatrix,
60 GrAA, const GrInstancedPipelineInfo&,
61 GrAAType*);
csmartdaltona7f29642016-07-07 08:49:11 -070062
Brian Salomonf8334782017-01-03 09:42:58 -050063 std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordOval(const SkRect&, const SkMatrix&,
64 GrColor, GrAA,
65 const GrInstancedPipelineInfo&,
66 GrAAType*);
csmartdaltona7f29642016-07-07 08:49:11 -070067
Brian Salomonf8334782017-01-03 09:42:58 -050068 std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordRRect(const SkRRect&, const SkMatrix&,
69 GrColor, GrAA,
70 const GrInstancedPipelineInfo&,
71 GrAAType*);
csmartdaltona7f29642016-07-07 08:49:11 -070072
Brian Salomonf8334782017-01-03 09:42:58 -050073 std::unique_ptr<GrDrawOp> SK_WARN_UNUSED_RESULT recordDRRect(const SkRRect& outer,
74 const SkRRect& inner,
75 const SkMatrix&, GrColor, GrAA,
76 const GrInstancedPipelineInfo&,
77 GrAAType*);
csmartdaltona7f29642016-07-07 08:49:11 -070078
79 /**
80 * Compiles all recorded draws into GPU buffers and allows the client to begin flushing the
Brian Salomon99ad1642016-12-16 09:50:45 -050081 * ops created by this class.
csmartdaltona7f29642016-07-07 08:49:11 -070082 */
83 void beginFlush(GrResourceProvider*);
84
85 /**
Brian Salomon99ad1642016-12-16 09:50:45 -050086 * Called once the ops created previously by this class have all been released. Allows the
csmartdaltona7f29642016-07-07 08:49:11 -070087 * client to begin recording draws again.
88 */
89 void endFlush();
90
91 enum class ResetType : bool {
92 kDestroy,
93 kAbandon
94 };
95
96 /**
97 * Resets all GPU resources, including those that are held long term. They will be lazily
98 * reinitialized if the class begins to be used again.
99 */
100 void resetGpuResources(ResetType);
101
102protected:
Brian Salomon99ad1642016-12-16 09:50:45 -0500103 class Op : public GrDrawOp {
csmartdaltona7f29642016-07-07 08:49:11 -0700104 public:
Brian Salomon99ad1642016-12-16 09:50:45 -0500105 SK_DECLARE_INTERNAL_LLIST_INTERFACE(Op);
csmartdaltona7f29642016-07-07 08:49:11 -0700106
Brian Salomon99ad1642016-12-16 09:50:45 -0500107 ~Op() override;
108 const char* name() const override { return "InstancedRendering::Op"; }
csmartdaltona7f29642016-07-07 08:49:11 -0700109
Brian Salomon7c3e7182016-12-01 09:35:30 -0500110 SkString dumpInfo() const override {
111 SkString string;
Brian Salomonaf9847e2017-03-01 11:28:27 -0500112 string.printf(
113 "AA: %d, ShapeTypes: 0x%02x, IShapeTypes: 0x%02x, Persp %d, "
114 "NonSquare: %d, PLoad: %0.2f, Tracked: %d, NumDraws: %d, "
115 "GeomChanges: %d\n",
116 (unsigned)fInfo.fAAType,
117 fInfo.fShapeTypes,
118 fInfo.fInnerShapeTypes,
119 fInfo.fHasPerspective,
120 fInfo.fNonSquare,
121 fPixelLoad,
122 fIsTracked,
123 fNumDraws,
124 fNumChangesInGeometry);
Brian Salomon7c3e7182016-12-01 09:35:30 -0500125 string.append(DumpPipelineInfo(*this->pipeline()));
126 string.append(INHERITED::dumpInfo());
127 return string;
128 }
129
csmartdaltona7f29642016-07-07 08:49:11 -0700130 struct Draw {
131 Instance fInstance;
132 IndexRange fGeometry;
133 Draw* fNext;
134 };
135
136 Draw& getSingleDraw() const { SkASSERT(fHeadDraw && !fHeadDraw->fNext); return *fHeadDraw; }
137 Instance& getSingleInstance() const { return this->getSingleDraw().fInstance; }
138
139 void appendRRectParams(const SkRRect&);
140 void appendParamsTexel(const SkScalar* vals, int count);
141 void appendParamsTexel(SkScalar x, SkScalar y, SkScalar z, SkScalar w);
142 void appendParamsTexel(SkScalar x, SkScalar y, SkScalar z);
143
144 protected:
Brian Salomon99ad1642016-12-16 09:50:45 -0500145 Op(uint32_t classID, InstancedRendering* ir);
csmartdaltona7f29642016-07-07 08:49:11 -0700146
Brian Salomon99ad1642016-12-16 09:50:45 -0500147 InstancedRendering* const fInstancedRendering;
148 OpInfo fInfo;
149 SkScalar fPixelLoad;
150 SkSTArray<5, ParamsTexel, true> fParams;
151 bool fIsTracked;
152 int fNumDraws;
153 int fNumChangesInGeometry;
154 Draw* fHeadDraw;
155 Draw* fTailDraw;
csmartdaltona7f29642016-07-07 08:49:11 -0700156
Brian Salomon92aee3d2016-12-21 09:20:25 -0500157 private:
Brian Salomon5298dc82017-02-22 11:52:03 -0500158 void getFragmentProcessorAnalysisInputs(
159 FragmentProcessorAnalysisInputs* input) const override;
Brian Salomon92aee3d2016-12-21 09:20:25 -0500160 void applyPipelineOptimizations(const GrPipelineOptimizations&) override;
161 bool onCombineIfPossible(GrOp* other, const GrCaps& caps) override;
162 void onPrepare(GrOpFlushState*) override {}
Brian Salomonbde42852016-12-21 11:37:49 -0500163 void onExecute(GrOpFlushState*, const SkRect& bounds) override;
Brian Salomon92aee3d2016-12-21 09:20:25 -0500164
Brian Salomon9afd3712016-12-01 10:59:09 -0500165 typedef GrDrawOp INHERITED;
csmartdaltona7f29642016-07-07 08:49:11 -0700166
167 friend class InstancedRendering;
168 };
169
Brian Salomon99ad1642016-12-16 09:50:45 -0500170 typedef SkTInternalLList<Op> OpList;
csmartdaltona7f29642016-07-07 08:49:11 -0700171
csmartdaltone0d36292016-07-29 08:14:20 -0700172 InstancedRendering(GrGpu* gpu);
csmartdaltona7f29642016-07-07 08:49:11 -0700173
Brian Salomon99ad1642016-12-16 09:50:45 -0500174 const OpList& trackedOps() const { return fTrackedOps; }
Hal Canary144caf52016-11-07 17:57:18 -0500175 const GrBuffer* vertexBuffer() const { SkASSERT(fVertexBuffer); return fVertexBuffer.get(); }
176 const GrBuffer* indexBuffer() const { SkASSERT(fIndexBuffer); return fIndexBuffer.get(); }
csmartdaltona7f29642016-07-07 08:49:11 -0700177
178 virtual void onBeginFlush(GrResourceProvider*) = 0;
Brian Salomon99ad1642016-12-16 09:50:45 -0500179 virtual void onDraw(const GrPipeline&, const InstanceProcessor&, const Op*) = 0;
csmartdaltona7f29642016-07-07 08:49:11 -0700180 virtual void onEndFlush() = 0;
181 virtual void onResetGpuResources(ResetType) = 0;
182
183private:
184 enum class State : bool {
185 kRecordingDraws,
186 kFlushing
187 };
188
Brian Salomonf8334782017-01-03 09:42:58 -0500189 std::unique_ptr<Op> SK_WARN_UNUSED_RESULT recordShape(ShapeType, const SkRect& bounds,
190 const SkMatrix& viewMatrix, GrColor,
191 const SkRect& localRect, GrAA aa,
192 const GrInstancedPipelineInfo&,
193 GrAAType*);
csmartdaltona7f29642016-07-07 08:49:11 -0700194
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500195 bool selectAntialiasMode(const SkMatrix& viewMatrix, GrAA aa, const GrInstancedPipelineInfo&,
Brian Salomonaf9847e2017-03-01 11:28:27 -0500196 GrAAType*);
csmartdaltona7f29642016-07-07 08:49:11 -0700197
Brian Salomonf8334782017-01-03 09:42:58 -0500198 virtual std::unique_ptr<Op> makeOp() = 0;
csmartdaltona7f29642016-07-07 08:49:11 -0700199
Brian Salomon99ad1642016-12-16 09:50:45 -0500200 const sk_sp<GrGpu> fGpu;
201 State fState;
202 GrObjectMemoryPool<Op::Draw> fDrawPool;
203 SkSTArray<1024, ParamsTexel, true> fParams;
204 OpList fTrackedOps;
205 sk_sp<const GrBuffer> fVertexBuffer;
206 sk_sp<const GrBuffer> fIndexBuffer;
207 sk_sp<GrBuffer> fParamsBuffer;
csmartdaltona7f29642016-07-07 08:49:11 -0700208};
209
210}
211
212#endif