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