• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
GrProcessorKeyBuilder(SkTArray<unsigned char,true> * data)35     GrProcessorKeyBuilder(SkTArray<unsigned char, true>* data) : fData(data), fCount(0) {
36         SkASSERT(0 == fData->count() % sizeof(uint32_t));
37     }
38 
add32(uint32_t v)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. */
add32n(int count)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 
size()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 */
dumpInfo()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 
requiredFeatures()90     RequiredFeatures requiredFeatures() const { return fRequiredFeatures; }
91 
92     void* operator new(size_t size);
93     void operator delete(void* target);
94 
new(size_t size,void * placement)95     void* operator new(size_t size, void* placement) {
96         return ::operator new(size, placement);
97     }
delete(void * target,void * placement)98     void operator delete(void* target, void* placement) {
99         ::operator delete(target, placement);
100     }
101 
102     /** Helper for down-casting to a GrProcessor subclass */
cast()103     template <typename T> const T& cast() const { return *static_cast<const T*>(this); }
104 
classID()105     uint32_t classID() const { SkASSERT(kIllegalProcessorClassID != fClassID); return fClassID; }
106 
107 protected:
GrProcessor()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      */
setWillUseSampleLocations()115     void setWillUseSampleLocations() { fRequiredFeatures |= kSampleLocations_RequiredFeature; }
116 
combineRequiredFeatures(const GrProcessor & other)117     void combineRequiredFeatures(const GrProcessor& other) {
118         fRequiredFeatures |= other.fRequiredFeatures;
119     }
120 
initClassID()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 
GenClassID()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 
numTextureSamplers()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(). */
textureSampler(int index)164     const TextureSampler& textureSampler(int index) const { return *fTextureSamplers[index]; }
165 
numBuffers()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(). */
bufferAccess(int index)170     const BufferAccess& bufferAccess(int index) const { return *fBufferAccesses[index]; }
171 
numImageStorages()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(). */
imageStorageAccess(int index)176     const ImageStorageAccess& imageStorageAccess(int index) const {
177         return *fImageStorageAccesses[index];
178     }
179 
180     bool instantiate(GrResourceProvider* resourceProvider) const;
181 
182 protected:
GrResourceIOProcessor()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.
instantiate(GrResourceProvider * resourceProvider)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
peekTexture()248     GrTexture* peekTexture() const {
249         SkASSERT(fProxyRef.get()->priv().peekTexture());
250         return fProxyRef.get()->priv().peekTexture();
251     }
252 
proxy()253     GrTextureProxy* proxy() const { return fProxyRef.get()->asTextureProxy(); }
visibility()254     GrShaderFlags visibility() const { return fVisibility; }
params()255     const GrSamplerParams& params() const { return fParams; }
256 
isInitialized()257     bool isInitialized() const { return SkToBool(fProxyRef.get()); }
258     /**
259      * For internal use by GrProcessor.
260      */
programProxy()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 
texelConfig()300     GrPixelConfig texelConfig() const { return fTexelConfig; }
buffer()301     GrBuffer* buffer() const { return fBuffer.get(); }
visibility()302     GrShaderFlags visibility() const { return fVisibility; }
303 
304     /**
305      * For internal use by GrProcessor.
306      */
programBuffer()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 
proxy()334     GrTextureProxy* proxy() const { return fProxyRef.get()->asTextureProxy(); }
visibility()335     GrShaderFlags visibility() const { return fVisibility; }
ioType()336     GrIOType ioType() const { return fProxyRef.ioType(); }
format()337     GrImageStorageFormat format() const { return fFormat; }
memoryModel()338     GrSLMemoryModel memoryModel() const { return fMemoryModel; }
339     GrSLRestrict restrict() const { return fRestrict; }
340 
341     // 'instantiate' should only ever be called at flush time.
instantiate(GrResourceProvider * resourceProvider)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
peekTexture()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      */
programProxy()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