Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2012 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 GrProcessor_DEFINED
      9 #define GrProcessor_DEFINED
     10 
     11 #include "../private/SkAtomics.h"
     12 #include "GrBuffer.h"
     13 #include "GrColor.h"
     14 #include "GrGpuResourceRef.h"
     15 #include "GrProcessorUnitTest.h"
     16 #include "GrProgramElement.h"
     17 #include "GrSamplerParams.h"
     18 #include "GrShaderVar.h"
     19 #include "GrSurfaceProxyPriv.h"
     20 #include "GrTextureProxy.h"
     21 #include "SkMath.h"
     22 #include "SkString.h"
     23 
     24 class GrContext;
     25 class GrCoordTransform;
     26 class GrInvariantOutput;
     27 class GrResourceProvider;
     28 
     29 /**
     30  * Used by processors to build their keys. It incorporates each per-processor key into a larger
     31  * shader key.
     32  */
     33 class GrProcessorKeyBuilder {
     34 public:
     35     GrProcessorKeyBuilder(SkTArray<unsigned char, true>* data) : fData(data), fCount(0) {
     36         SkASSERT(0 == fData->count() % sizeof(uint32_t));
     37     }
     38 
     39     void add32(uint32_t v) {
     40         ++fCount;
     41         fData->push_back_n(4, reinterpret_cast<uint8_t*>(&v));
     42     }
     43 
     44     /** Inserts count uint32_ts into the key. The returned pointer is only valid until the next
     45         add*() call. */
     46     uint32_t* SK_WARN_UNUSED_RESULT add32n(int count) {
     47         SkASSERT(count > 0);
     48         fCount += count;
     49         return reinterpret_cast<uint32_t*>(fData->push_back_n(4 * count));
     50     }
     51 
     52     size_t size() const { return sizeof(uint32_t) * fCount; }
     53 
     54 private:
     55     SkTArray<uint8_t, true>* fData; // unowned ptr to the larger key.
     56     int fCount;                     // number of uint32_ts added to fData by the processor.
     57 };
     58 
     59 /** Provides custom shader code to the Ganesh shading pipeline. GrProcessor objects *must* be
     60     immutable: after being constructed, their fields may not change.
     61 
     62     Dynamically allocated GrProcessors are managed by a per-thread memory pool. The ref count of an
     63     processor must reach 0 before the thread terminates and the pool is destroyed.
     64  */
     65 class GrProcessor {
     66 public:
     67     virtual ~GrProcessor() = default;
     68 
     69     /** Human-meaningful string to identify this prcoessor; may be embedded in generated shader
     70         code. */
     71     virtual const char* name() const = 0;
     72 
     73     /** Human-readable dump of all information */
     74     virtual SkString dumpInfo() const {
     75         SkString str;
     76         str.appendf("Missing data");
     77         return str;
     78     }
     79 
     80     /**
     81      * Platform specific built-in features that a processor can request for the fragment shader.
     82      */
     83     enum RequiredFeatures {
     84         kNone_RequiredFeatures             = 0,
     85         kSampleLocations_RequiredFeature   = 1 << 0
     86     };
     87 
     88     GR_DECL_BITFIELD_OPS_FRIENDS(RequiredFeatures);
     89 
     90     RequiredFeatures requiredFeatures() const { return fRequiredFeatures; }
     91 
     92     void* operator new(size_t size);
     93     void operator delete(void* target);
     94 
     95     void* operator new(size_t size, void* placement) {
     96         return ::operator new(size, placement);
     97     }
     98     void operator delete(void* target, void* placement) {
     99         ::operator delete(target, placement);
    100     }
    101 
    102     /** Helper for down-casting to a GrProcessor subclass */
    103     template <typename T> const T& cast() const { return *static_cast<const T*>(this); }
    104 
    105     uint32_t classID() const { SkASSERT(kIllegalProcessorClassID != fClassID); return fClassID; }
    106 
    107 protected:
    108     GrProcessor() : fClassID(kIllegalProcessorClassID), fRequiredFeatures(kNone_RequiredFeatures) {}
    109 
    110     /**
    111      * If the prcoessor will generate code that uses platform specific built-in features, then it
    112      * must call these methods from its constructor. Otherwise, requests to use these features will
    113      * be denied.
    114      */
    115     void setWillUseSampleLocations() { fRequiredFeatures |= kSampleLocations_RequiredFeature; }
    116 
    117     void combineRequiredFeatures(const GrProcessor& other) {
    118         fRequiredFeatures |= other.fRequiredFeatures;
    119     }
    120 
    121     template <typename PROC_SUBCLASS> void initClassID() {
    122          static uint32_t kClassID = GenClassID();
    123          fClassID = kClassID;
    124     }
    125 
    126 private:
    127     GrProcessor(const GrProcessor&) = delete;
    128     GrProcessor& operator=(const GrProcessor&) = delete;
    129 
    130     static uint32_t GenClassID() {
    131         // fCurrProcessorClassID has been initialized to kIllegalProcessorClassID. The
    132         // atomic inc returns the old value not the incremented value. So we add
    133         // 1 to the returned value.
    134         uint32_t id = static_cast<uint32_t>(sk_atomic_inc(&gCurrProcessorClassID)) + 1;
    135         if (!id) {
    136             SkFAIL("This should never wrap as it should only be called once for each GrProcessor "
    137                    "subclass.");
    138         }
    139         return id;
    140     }
    141 
    142     enum {
    143         kIllegalProcessorClassID = 0,
    144     };
    145     static int32_t gCurrProcessorClassID;
    146 
    147     uint32_t                                        fClassID;
    148     RequiredFeatures                                fRequiredFeatures;
    149 };
    150 
    151 GR_MAKE_BITFIELD_OPS(GrProcessor::RequiredFeatures);
    152 
    153 /** A GrProcessor with the ability to access textures, buffers, and image storages. */
    154 class GrResourceIOProcessor : public GrProcessor {
    155 public:
    156     class TextureSampler;
    157     class BufferAccess;
    158     class ImageStorageAccess;
    159 
    160     int numTextureSamplers() const { return fTextureSamplers.count(); }
    161 
    162     /** Returns the access pattern for the texture at index. index must be valid according to
    163         numTextureSamplers(). */
    164     const TextureSampler& textureSampler(int index) const { return *fTextureSamplers[index]; }
    165 
    166     int numBuffers() const { return fBufferAccesses.count(); }
    167 
    168     /** Returns the access pattern for the buffer at index. index must be valid according to
    169         numBuffers(). */
    170     const BufferAccess& bufferAccess(int index) const { return *fBufferAccesses[index]; }
    171 
    172     int numImageStorages() const { return fImageStorageAccesses.count(); }
    173 
    174     /** Returns the access object for the image at index. index must be valid according to
    175         numImages(). */
    176     const ImageStorageAccess& imageStorageAccess(int index) const {
    177         return *fImageStorageAccesses[index];
    178     }
    179 
    180     bool instantiate(GrResourceProvider* resourceProvider) const;
    181 
    182 protected:
    183     GrResourceIOProcessor() {}
    184 
    185     /**
    186      * Subclasses call these from their constructor to register sampler/image sources. The processor
    187      * subclass manages the lifetime of the objects (these functions only store pointers). The
    188      * TextureSampler and/or BufferAccess instances are typically member fields of the GrProcessor
    189      * subclass. These must only be called from the constructor because GrProcessors are immutable.
    190      */
    191     void addTextureSampler(const TextureSampler*);
    192     void addBufferAccess(const BufferAccess*);
    193     void addImageStorageAccess(const ImageStorageAccess*);
    194 
    195     bool hasSameSamplersAndAccesses(const GrResourceIOProcessor&) const;
    196 
    197     // These methods can be used by derived classes that also derive from GrProgramElement.
    198     void addPendingIOs() const;
    199     void removeRefs() const;
    200     void pendingIOComplete() const;
    201 
    202 private:
    203     SkSTArray<4, const TextureSampler*, true> fTextureSamplers;
    204     SkSTArray<1, const BufferAccess*, true> fBufferAccesses;
    205     SkSTArray<1, const ImageStorageAccess*, true> fImageStorageAccesses;
    206 
    207     typedef GrProcessor INHERITED;
    208 };
    209 
    210 /**
    211  * Used to represent a texture that is required by a GrResourceIOProcessor. It holds a GrTexture
    212  * along with an associated GrSamplerParams. TextureSamplers don't perform any coord manipulation to
    213  * account for texture origin.
    214  */
    215 class GrResourceIOProcessor::TextureSampler : public SkNoncopyable {
    216 public:
    217     /**
    218      * Must be initialized before adding to a GrProcessor's texture access list.
    219      */
    220     TextureSampler();
    221 
    222     TextureSampler(sk_sp<GrTextureProxy>, const GrSamplerParams&);
    223     explicit TextureSampler(sk_sp<GrTextureProxy>,
    224                             GrSamplerParams::FilterMode = GrSamplerParams::kNone_FilterMode,
    225                             SkShader::TileMode tileXAndY = SkShader::kClamp_TileMode,
    226                             GrShaderFlags visibility = kFragment_GrShaderFlag);
    227     void reset(sk_sp<GrTextureProxy>, const GrSamplerParams&,
    228                GrShaderFlags visibility = kFragment_GrShaderFlag);
    229     void reset(sk_sp<GrTextureProxy>,
    230                GrSamplerParams::FilterMode = GrSamplerParams::kNone_FilterMode,
    231                SkShader::TileMode tileXAndY = SkShader::kClamp_TileMode,
    232                GrShaderFlags visibility = kFragment_GrShaderFlag);
    233 
    234     bool operator==(const TextureSampler& that) const {
    235         return this->proxy()->underlyingUniqueID() == that.proxy()->underlyingUniqueID() &&
    236                fParams == that.fParams &&
    237                fVisibility == that.fVisibility;
    238     }
    239 
    240     bool operator!=(const TextureSampler& other) const { return !(*this == other); }
    241 
    242     // 'instantiate' should only ever be called at flush time.
    243     bool instantiate(GrResourceProvider* resourceProvider) const {
    244         return SkToBool(fProxyRef.get()->instantiate(resourceProvider));
    245     }
    246 
    247     // 'peekTexture' should only ever be called after a successful 'instantiate' call
    248     GrTexture* peekTexture() const {
    249         SkASSERT(fProxyRef.get()->priv().peekTexture());
    250         return fProxyRef.get()->priv().peekTexture();
    251     }
    252 
    253     GrTextureProxy* proxy() const { return fProxyRef.get()->asTextureProxy(); }
    254     GrShaderFlags visibility() const { return fVisibility; }
    255     const GrSamplerParams& params() const { return fParams; }
    256 
    257     bool isInitialized() const { return SkToBool(fProxyRef.get()); }
    258     /**
    259      * For internal use by GrProcessor.
    260      */
    261     const GrSurfaceProxyRef* programProxy() const { return &fProxyRef; }
    262 
    263 private:
    264     GrSurfaceProxyRef               fProxyRef;
    265     GrSamplerParams                 fParams;
    266     GrShaderFlags                   fVisibility;
    267 
    268     typedef SkNoncopyable INHERITED;
    269 };
    270 
    271 /**
    272  * Used to represent a texel buffer that will be read in a GrResourceIOProcessor. It holds a
    273  * GrBuffer along with an associated offset and texel config.
    274  */
    275 class GrResourceIOProcessor::BufferAccess : public SkNoncopyable {
    276 public:
    277     BufferAccess() = default;
    278     BufferAccess(GrPixelConfig texelConfig, GrBuffer* buffer,
    279                  GrShaderFlags visibility = kFragment_GrShaderFlag) {
    280         this->reset(texelConfig, buffer, visibility);
    281     }
    282     /**
    283      * Must be initialized before adding to a GrProcessor's buffer access list.
    284      */
    285     void reset(GrPixelConfig texelConfig, GrBuffer* buffer,
    286                GrShaderFlags visibility = kFragment_GrShaderFlag) {
    287         fTexelConfig = texelConfig;
    288         fBuffer.set(SkRef(buffer), kRead_GrIOType);
    289         fVisibility = visibility;
    290     }
    291 
    292     bool operator==(const BufferAccess& that) const {
    293         return fTexelConfig == that.fTexelConfig &&
    294                this->buffer() == that.buffer() &&
    295                fVisibility == that.fVisibility;
    296     }
    297 
    298     bool operator!=(const BufferAccess& that) const { return !(*this == that); }
    299 
    300     GrPixelConfig texelConfig() const { return fTexelConfig; }
    301     GrBuffer* buffer() const { return fBuffer.get(); }
    302     GrShaderFlags visibility() const { return fVisibility; }
    303 
    304     /**
    305      * For internal use by GrProcessor.
    306      */
    307     const GrGpuResourceRef* programBuffer() const { return &fBuffer;}
    308 
    309 private:
    310     GrPixelConfig fTexelConfig;
    311     GrTGpuResourceRef<GrBuffer> fBuffer;
    312     GrShaderFlags fVisibility;
    313 
    314     typedef SkNoncopyable INHERITED;
    315 };
    316 
    317 /**
    318  * This is used by a GrProcessor to access a texture using image load/store in its shader code.
    319  * ImageStorageAccesses don't perform any coord manipulation to account for texture origin.
    320  * Currently the format of the load/store data in the shader is inferred from the texture config,
    321  * though it could be made explicit.
    322  */
    323 class GrResourceIOProcessor::ImageStorageAccess : public SkNoncopyable {
    324 public:
    325     ImageStorageAccess(sk_sp<GrTextureProxy>, GrIOType, GrSLMemoryModel, GrSLRestrict,
    326                        GrShaderFlags visibility = kFragment_GrShaderFlag);
    327 
    328     bool operator==(const ImageStorageAccess& that) const {
    329         return this->proxy() == that.proxy() && fVisibility == that.fVisibility;
    330     }
    331 
    332     bool operator!=(const ImageStorageAccess& that) const { return !(*this == that); }
    333 
    334     GrTextureProxy* proxy() const { return fProxyRef.get()->asTextureProxy(); }
    335     GrShaderFlags visibility() const { return fVisibility; }
    336     GrIOType ioType() const { return fProxyRef.ioType(); }
    337     GrImageStorageFormat format() const { return fFormat; }
    338     GrSLMemoryModel memoryModel() const { return fMemoryModel; }
    339     GrSLRestrict restrict() const { return fRestrict; }
    340 
    341     // 'instantiate' should only ever be called at flush time.
    342     bool instantiate(GrResourceProvider* resourceProvider) const {
    343         return SkToBool(fProxyRef.get()->instantiate(resourceProvider));
    344     }
    345     // 'peekTexture' should only ever be called after a successful 'instantiate' call
    346     GrTexture* peekTexture() const {
    347         SkASSERT(fProxyRef.get()->priv().peekTexture());
    348         return fProxyRef.get()->priv().peekTexture();
    349     }
    350 
    351     /**
    352      * For internal use by GrProcessor.
    353      */
    354     const GrSurfaceProxyRef* programProxy() const { return &fProxyRef; }
    355 
    356 private:
    357     GrSurfaceProxyRef    fProxyRef;
    358     GrShaderFlags        fVisibility;
    359     GrImageStorageFormat fFormat;
    360     GrSLMemoryModel      fMemoryModel;
    361     GrSLRestrict         fRestrict;
    362     typedef SkNoncopyable INHERITED;
    363 };
    364 
    365 #endif
    366