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:
GrProcessorKeyBuilder(SkTArray<unsigned char,true> * data)34     GrProcessorKeyBuilder(SkTArray<unsigned char, true>* data) : fData(data), fCount(0) {
35         SkASSERT(0 == fData->count() % sizeof(uint32_t));
36     }
37 
add32(uint32_t v)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. */
add32n(int count)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 
size()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 */
dumpInfo()77     virtual SkString dumpInfo() const {
78         SkString str;
79         str.appendf("Missing data");
80         return str;
81     }
82 
numTextureSamplers()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(). */
textureSampler(int index)87     const TextureSampler& textureSampler(int index) const { return *fTextureSamplers[index]; }
88 
numBuffers()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(). */
bufferAccess(int index)93     const BufferAccess& bufferAccess(int index) const { return *fBufferAccesses[index]; }
94 
numImageStorages()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(). */
imageStorageAccess(int index)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 
requiredFeatures()113     RequiredFeatures requiredFeatures() const { return fRequiredFeatures; }
114 
115     void* operator new(size_t size);
116     void operator delete(void* target);
117 
new(size_t size,void * placement)118     void* operator new(size_t size, void* placement) {
119         return ::operator new(size, placement);
120     }
delete(void * target,void * placement)121     void operator delete(void* target, void* placement) {
122         ::operator delete(target, placement);
123     }
124 
125     /** Helper for down-casting to a GrProcessor subclass */
cast()126     template <typename T> const T& cast() const { return *static_cast<const T*>(this); }
127 
classID()128     uint32_t classID() const { SkASSERT(kIllegalProcessorClassID != fClassID); return fClassID; }
129 
130 protected:
GrProcessor()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      */
setWillUseSampleLocations()150     void setWillUseSampleLocations() { fRequiredFeatures |= kSampleLocations_RequiredFeature; }
151 
combineRequiredFeatures(const GrProcessor & other)152     void combineRequiredFeatures(const GrProcessor& other) {
153         fRequiredFeatures |= other.fRequiredFeatures;
154     }
155 
initClassID()156     template <typename PROC_SUBCLASS> void initClassID() {
157          static uint32_t kClassID = GenClassID();
158          fClassID = kClassID;
159     }
160 
161 private:
GenClassID()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 
texture()240     GrTexture* texture() const { return fTexture.get(); }
visibility()241     GrShaderFlags visibility() const { return fVisibility; }
params()242     const GrSamplerParams& params() const { return fParams; }
243 
244     /**
245      * For internal use by GrProcessor.
246      */
programTexture()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 
texelConfig()289     GrPixelConfig texelConfig() const { return fTexelConfig; }
buffer()290     GrBuffer* buffer() const { return fBuffer.get(); }
visibility()291     GrShaderFlags visibility() const { return fVisibility; }
292 
293     /**
294      * For internal use by GrProcessor.
295      */
programBuffer()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 
texture()323     GrTexture* texture() const { return fTexture.get(); }
visibility()324     GrShaderFlags visibility() const { return fVisibility; }
ioType()325     GrIOType ioType() const { return fTexture.ioType(); }
format()326     GrImageStorageFormat format() const { return fFormat; }
memoryModel()327     GrSLMemoryModel memoryModel() const { return fMemoryModel; }
328     GrSLRestrict restrict() const { return fRestrict; }
329 
330     /**
331      * For internal use by GrProcessor.
332      */
programTexture()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