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