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