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: ~InstancedRendering()37 virtual ~InstancedRendering() { SkASSERT(State::kRecordingDraws == fState); } 38 gpu()39 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; name()104 const char* name() const override { return "InstancedRendering::Op"; } 105 dumpInfo()106 SkString dumpInfo() const override { 107 SkString string; 108 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); 121 string.append(INHERITED::dumpInfo()); 122 return string; 123 } 124 125 struct Draw { 126 Instance fInstance; 127 IndexRange fGeometry; 128 Draw* fNext; 129 }; 130 getSingleDraw()131 Draw& getSingleDraw() const { SkASSERT(fHeadDraw && !fHeadDraw->fNext); return *fHeadDraw; } getSingleInstance()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); fixedFunctionFlags()138 FixedFunctionFlags fixedFunctionFlags() const override { 139 return GrAATypeIsHW(fInfo.aaType()) ? FixedFunctionFlags::kUsesHWAA 140 : 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 fDrawColorsAreOpaque : 1; 157 bool fDrawColorsAreSame : 1; 158 int fNumDraws; 159 int fNumChangesInGeometry; 160 Draw* fHeadDraw; 161 Draw* fTailDraw; 162 163 private: 164 bool onCombineIfPossible(GrOp* other, const GrCaps& caps) override; onPrepare(GrOpFlushState *)165 void onPrepare(GrOpFlushState*) override {} 166 void onExecute(GrOpFlushState*) override; 167 168 typedef GrDrawOp INHERITED; 169 170 friend class InstancedRendering; 171 }; 172 173 typedef SkTInternalLList<Op> OpList; 174 175 InstancedRendering(GrGpu* gpu); 176 trackedOps()177 const OpList& trackedOps() const { return fTrackedOps; } vertexBuffer()178 const GrBuffer* vertexBuffer() const { SkASSERT(fVertexBuffer); return fVertexBuffer.get(); } indexBuffer()179 const GrBuffer* indexBuffer() const { SkASSERT(fIndexBuffer); return fIndexBuffer.get(); } 180 181 virtual void onBeginFlush(GrResourceProvider*) = 0; 182 virtual void onDraw(const GrPipeline&, const InstanceProcessor&, const Op*) = 0; 183 virtual void onEndFlush() = 0; 184 virtual void onResetGpuResources(ResetType) = 0; 185 186 private: 187 enum class State : bool { 188 kRecordingDraws, 189 kFlushing 190 }; 191 192 std::unique_ptr<Op> SK_WARN_UNUSED_RESULT recordShape(ShapeType, const SkRect& bounds, 193 const SkMatrix& viewMatrix, GrPaint&&, 194 const SkRect& localRect, GrAA aa, 195 const GrInstancedPipelineInfo&); 196 197 bool selectAntialiasMode(const SkMatrix& viewMatrix, GrAA aa, const GrInstancedPipelineInfo&, 198 GrAAType*); 199 200 virtual std::unique_ptr<Op> makeOp(GrPaint&&) = 0; 201 202 const sk_sp<GrGpu> fGpu; 203 State fState; 204 GrObjectMemoryPool<Op::Draw> fDrawPool; 205 SkSTArray<1024, ParamsTexel, true> fParams; 206 OpList fTrackedOps; 207 sk_sp<const GrBuffer> fVertexBuffer; 208 sk_sp<const GrBuffer> fIndexBuffer; 209 sk_sp<GrBuffer> fParamsBuffer; 210 }; 211 212 } 213 214 #endif 215