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