| Index: src/gpu/GrInstancedRendering.h
|
| diff --git a/src/gpu/GrInstancedRendering.h b/src/gpu/GrInstancedRendering.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d016f0f0787f4d25c7e9fb379b34d3cfadbae5c1
|
| --- /dev/null
|
| +++ b/src/gpu/GrInstancedRendering.h
|
| @@ -0,0 +1,222 @@
|
| +/*
|
| + * Copyright 2016 Google Inc.
|
| + *
|
| + * Use of this source code is governed by a BSD-style license that can be
|
| + * found in the LICENSE file.
|
| + */
|
| +
|
| +#ifndef GrInstancedRendering_DEFINED
|
| +#define GrInstancedRendering_DEFINED
|
| +
|
| +#include "GrAllocator.h"
|
| +#include "GrInstancedRenderingTypes.h"
|
| +#include "batches/GrDrawBatch.h"
|
| +
|
| +class GrInstanceProcessor;
|
| +class GrResourceProvider;
|
| +
|
| +/**
|
| + * This class serves as a centralized clearinghouse for instanced rendering. It accumulates data for
|
| + * instanced draws into one location, and creates special batches that pull from this data. The
|
| + * nature of instanced rendering allows these batches to combine well and render efficiently.
|
| + *
|
| + * During a flush, this class assembles the accumulated draw data into a single vertex and texel
|
| + * buffer, and its subclass draws the batches using backend-specific instanced rendering APIs.
|
| + *
|
| + * This class is responsible for the CPU side of instanced rendering. Shaders are implemented by
|
| + * GrInstanceProcessor.
|
| + */
|
| +class GrInstancedRendering : public SkNoncopyable, protected GrInstancedRenderingTypes {
|
| +public:
|
| + virtual ~GrInstancedRendering() { SkASSERT(State::kRecordingShapes == fState); }
|
| +
|
| + GrGpu* gpu() const { return fGpu; }
|
| +
|
| + enum Flags {
|
| + kStencilWrite_Flag = (1 << 0),
|
| + kStencilBufferMSAA_Flag = (1 << 1),
|
| + kColorWrite_Flag = (1 << 2),
|
| + kColorBufferMSAA_Flag = (1 << 3),
|
| + /**
|
| + * This should not be set if the fragment shader uses derivatives, automatic mipmap LOD, or
|
| + * other features that depend on neighboring pixels.
|
| + */
|
| + kCanDiscardFragments_Flag = (1 << 4)
|
| + };
|
| +
|
| + /**
|
| + * These methods record a new instanced draw and return a batch that can render it. The client
|
| + * must call commitToGpu() before attempting to draw batches returned by this class. After
|
| + * commitToGpu(), it becomes invalid to record new draws until a subsequent call to restart().
|
| + *
|
| + * The caller is responsible to enable HW antialias in the GrPipelineBuilder if (and only if)
|
| + * the value of "antialias" is true and the draw is fully multisampled (e.g. stencil-only draw
|
| + * to a multisampled stencil buffer, stencil + color draw when both buffers are multisampled),
|
| + * or if the value of "requireHWAA" gets overwritten with true. requireHWAA will be left
|
| + * unchanged unless the batch requires HW antialias under different circumstances than those
|
| + * listed above (e.g. mixed samples).
|
| + */
|
| + GrDrawBatch* SK_WARN_UNUSED_RESULT recordRect(const SkRect&, const SkMatrix&, GrColor,
|
| + bool antialias, uint32_t flags,
|
| + bool* requireHWAA = nullptr);
|
| +
|
| + GrDrawBatch* SK_WARN_UNUSED_RESULT recordRect(const SkRect&, const SkMatrix&, GrColor,
|
| + const SkRect& localRect, bool antialias,
|
| + uint32_t flags, bool* requireHWAA = nullptr);
|
| +
|
| + GrDrawBatch* SK_WARN_UNUSED_RESULT recordRect(const SkRect&, const SkMatrix&, GrColor,
|
| + const SkMatrix& localMatrix, bool antialias,
|
| + uint32_t flags, bool* requireHWAA = nullptr);
|
| +
|
| + GrDrawBatch* SK_WARN_UNUSED_RESULT recordOval(const SkRect&, const SkMatrix&, GrColor,
|
| + bool antialias, uint32_t flags,
|
| + bool* requireHWAA = nullptr);
|
| +
|
| + GrDrawBatch* SK_WARN_UNUSED_RESULT recordRRect(const SkRRect&, const SkMatrix&, GrColor,
|
| + bool antialias, uint32_t flags,
|
| + bool* requireHWAA = nullptr);
|
| +
|
| + GrDrawBatch* SK_WARN_UNUSED_RESULT recordDRRect(const SkRRect& outer, const SkRRect& inner,
|
| + const SkMatrix&, GrColor, bool antialias,
|
| + uint32_t flags, bool* requireHWAA = nullptr);
|
| +
|
| + /**
|
| + * Commits all recorded draws to GPU memory and allows the client to begin drawing the batches
|
| + * created by this class.
|
| + */
|
| + void commitToGpu(GrResourceProvider*);
|
| +
|
| + /**
|
| + * Called once the batches created previously by this class have all been released. Allows the
|
| + * client to begin recording draws again.
|
| + */
|
| + void restart();
|
| +
|
| + enum class ClearType {
|
| + kDestroy,
|
| + kAbandon
|
| + };
|
| +
|
| + /**
|
| + * Clears all GPU resources, including those that are held long term. They will be lazily
|
| + * reinitialized if the class begins to be used again.
|
| + */
|
| + void clearGpuResources(ClearType);
|
| +
|
| +protected:
|
| + class Batch : public GrDrawBatch {
|
| + public:
|
| + virtual ~Batch() { fInUse = false; } // fInUse will continue to be accessed.
|
| +
|
| + const char* name() const override { return "Instanced Batch"; }
|
| +
|
| + void computePipelineOptimizations(GrInitInvariantOutput* color,
|
| + GrInitInvariantOutput* coverage,
|
| + GrBatchToXPOverrides*) const override;
|
| +
|
| + protected:
|
| + Batch(uint32_t classID, GrInstancedRendering* instRendering, AntialiasMode aa,
|
| + uint32_t flags, int instanceIdx)
|
| + : INHERITED(classID),
|
| + fInstancedRendering(instRendering),
|
| + fAntialiasMode(aa),
|
| + fFlags(flags),
|
| + fFirstInstanceIdx(instanceIdx),
|
| + fInUse(true) {
|
| +#ifdef SK_DEBUG
|
| + fIsCombined = false;
|
| +#endif
|
| + }
|
| +
|
| + void initBatchTracker(const GrXPOverridesForBatch&) override;
|
| +
|
| + void onPrepare(GrBatchFlushState*) override {}
|
| + void onDraw(GrBatchFlushState*) override;
|
| + void onDelete() const override;
|
| +
|
| + GrInstancedRendering* const fInstancedRendering;
|
| + const AntialiasMode fAntialiasMode;
|
| + const uint32_t fFlags;
|
| + const int fFirstInstanceIdx;
|
| + BatchTracker fTracker;
|
| + bool fInUse;
|
| +#ifdef SK_DEBUG
|
| + bool fIsCombined;
|
| +#endif
|
| +
|
| + typedef GrDrawBatch INHERITED;
|
| +
|
| + friend class GrInstancedRendering;
|
| + };
|
| +
|
| + class BatchAllocator : public GrAllocator {
|
| + public:
|
| + BatchAllocator(size_t sizeofBatchClass)
|
| + : INHERITED(sizeofBatchClass, kBatchesPerBlock, nullptr) {
|
| + fFirstBlock = sk_malloc_throw(kBatchesPerBlock * sizeofBatchClass);
|
| + this->setInitialBlock(fFirstBlock);
|
| + }
|
| +
|
| + ~BatchAllocator() {
|
| + sk_free(fFirstBlock);
|
| + }
|
| +
|
| + private:
|
| + enum { kBatchesPerBlock = 128 };
|
| +
|
| + void* fFirstBlock;
|
| +
|
| + typedef GrAllocator INHERITED;
|
| + };
|
| +
|
| + GrInstancedRendering(GrGpu* gpu, uint32_t supportedAAModes, size_t sizeofBatchClass);
|
| +
|
| + const GrBuffer* vertexBuffer() const { SkASSERT(fVertexBuffer); return fVertexBuffer; }
|
| + const GrBuffer* indexBuffer() const { SkASSERT(fIndexBuffer); return fIndexBuffer; }
|
| + const GrBuffer* instanceBuffer() const { SkASSERT(fInstanceBuffer); return fInstanceBuffer; }
|
| + const BatchAllocator* batchAllocator() const { return &fBatchAllocator; }
|
| +
|
| + virtual void onCommitToGpu(GrResourceProvider*) = 0;
|
| + virtual void onDraw(const GrPipeline&, const GrInstanceProcessor&, const Batch*) = 0;
|
| + virtual void onRestart() = 0;
|
| + virtual void onClearGpuResources(ClearType) = 0;
|
| +
|
| +#ifdef SK_DEBUG
|
| + int fInUseBatchCount;
|
| +#endif
|
| +
|
| +private:
|
| + enum class State {
|
| + kRecordingShapes,
|
| + kDrawingBatches
|
| + };
|
| +
|
| + Batch* SK_WARN_UNUSED_RESULT recordShape(ShapeType, const SkRect& bounds,
|
| + const SkMatrix& viewMatrix, GrColor,
|
| + const SkRect& localRect, bool antialias,
|
| + uint32_t flags, bool* requireHWAA);
|
| +
|
| + bool selectAntialiasMode(const SkMatrix& viewMatrix, bool antialias, uint32_t flags,
|
| + AntialiasMode*, bool* requireHWAA);
|
| +
|
| + void appendRRectParams(const SkRRect&, BatchTracker*);
|
| + void appendParamsTexel(const SkScalar* vals, int count);
|
| + void appendParamsTexel(float x, float y, float z, float w);
|
| + void appendParamsTexel(float x, float y, float z);
|
| +
|
| + virtual Batch* constructBatch(void* storage, AntialiasMode, uint32_t flags,
|
| + int instanceIdx) = 0;
|
| +
|
| + const SkAutoTUnref<GrGpu> fGpu;
|
| + const uint32_t fSupportedAAModes;
|
| + State fState;
|
| + SkSTArray<1024, Instance, true> fInstances;
|
| + SkSTArray<1024, ParamsTexel, true> fParams;
|
| + BatchAllocator fBatchAllocator;
|
| + SkAutoTUnref<const GrBuffer> fVertexBuffer;
|
| + SkAutoTUnref<const GrBuffer> fIndexBuffer;
|
| + SkAutoTUnref<const GrBuffer> fInstanceBuffer;
|
| + SkAutoTUnref<GrBuffer> fParamsBuffer;
|
| +};
|
| +
|
| +#endif
|
|
|