Home | History | Annotate | Download | only in instanced
      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     virtual ~InstancedRendering() { SkASSERT(State::kRecordingDraws == fState); }
     38 
     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;
    104         const char* name() const override { return "InstancedRendering::Op"; }
    105 
    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 
    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);
    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;
    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 
    177     const OpList& trackedOps() const { return fTrackedOps; }
    178     const GrBuffer* vertexBuffer() const { SkASSERT(fVertexBuffer); return fVertexBuffer.get(); }
    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