1 /* 2 * Copyright 2021 Google LLC 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 skgpu_graphite_Caps_DEFINED 9 #define skgpu_graphite_Caps_DEFINED 10 11 #include <optional> 12 #include <string> 13 #include <string_view> 14 15 #include "include/core/SkImageInfo.h" 16 #include "include/core/SkRefCnt.h" 17 #include "include/private/base/SkAlign.h" 18 #include "src/base/SkEnumBitMask.h" 19 #include "src/gpu/ResourceKey.h" 20 #include "src/gpu/Swizzle.h" 21 #include "src/gpu/graphite/ResourceTypes.h" 22 #include "src/gpu/graphite/TextureProxy.h" 23 #include "src/text/gpu/SDFTControl.h" 24 25 #if defined(GRAPHITE_TEST_UTILS) 26 #include "include/private/gpu/graphite/ContextOptionsPriv.h" 27 #endif 28 29 enum class SkBlendMode; 30 enum class SkTextureCompressionType; 31 class SkCapabilities; 32 33 namespace SkSL { struct ShaderCaps; } 34 35 namespace skgpu { class ShaderErrorHandler; } 36 37 namespace skgpu::graphite { 38 39 enum class BufferType : int; 40 struct ContextOptions; 41 class ComputePipelineDesc; 42 class GraphicsPipelineDesc; 43 class GraphiteResourceKey; 44 class RendererProvider; 45 struct RenderPassDesc; 46 class TextureInfo; 47 48 struct ResourceBindingRequirements { 49 // The required data layout rules for the contents of a uniform buffer. 50 Layout fUniformBufferLayout = Layout::kInvalid; 51 52 // The required data layout rules for the contents of a storage buffer. 53 Layout fStorageBufferLayout = Layout::kInvalid; 54 55 // Whether combined texture-sampler types are supported. Backends that do not support 56 // combined image samplers (i.e. sampler2D) require a texture and sampler object to be bound 57 // separately and their binding indices explicitly specified in the shader text. 58 bool fSeparateTextureAndSamplerBinding = false; 59 60 // Whether buffer, texture, and sampler resource bindings use distinct index ranges. 61 bool fDistinctIndexRanges = false; 62 }; 63 64 enum class DstReadRequirement { 65 kNone, 66 kTextureCopy, 67 kTextureSample, 68 kFramebufferFetch, 69 }; 70 71 class Caps { 72 public: 73 virtual ~Caps(); 74 shaderCaps()75 const SkSL::ShaderCaps* shaderCaps() const { return fShaderCaps.get(); } 76 77 sk_sp<SkCapabilities> capabilities() const; 78 79 #if defined(GRAPHITE_TEST_UTILS) deviceName()80 std::string_view deviceName() const { return fDeviceName; } 81 requestedPathRendererStrategy()82 PathRendererStrategy requestedPathRendererStrategy() const { 83 return fRequestedPathRendererStrategy; 84 } 85 #endif 86 87 virtual TextureInfo getDefaultSampledTextureInfo(SkColorType, 88 Mipmapped mipmapped, 89 Protected, 90 Renderable) const = 0; 91 92 virtual TextureInfo getTextureInfoForSampledCopy(const TextureInfo& textureInfo, 93 Mipmapped mipmapped) const = 0; 94 95 virtual TextureInfo getDefaultCompressedTextureInfo(SkTextureCompressionType, 96 Mipmapped mipmapped, 97 Protected) const = 0; 98 99 virtual TextureInfo getDefaultMSAATextureInfo(const TextureInfo& singleSampledInfo, 100 Discardable discardable) const = 0; 101 102 virtual TextureInfo getDefaultDepthStencilTextureInfo(SkEnumBitMask<DepthStencilFlags>, 103 uint32_t sampleCount, 104 Protected) const = 0; 105 106 virtual TextureInfo getDefaultStorageTextureInfo(SkColorType) const = 0; 107 108 // Get required depth attachment dimensions for a givin color attachment info and dimensions. 109 virtual SkISize getDepthAttachmentDimensions(const TextureInfo&, 110 const SkISize colorAttachmentDimensions) const; 111 112 virtual UniqueKey makeGraphicsPipelineKey(const GraphicsPipelineDesc&, 113 const RenderPassDesc&) const = 0; 114 virtual UniqueKey makeComputePipelineKey(const ComputePipelineDesc&) const = 0; 115 116 // Returns a GraphiteResourceKey based upon a SamplerDesc with any additional information that 117 // backends append within their implementation. By default, simply returns a key based upon 118 // the SamplerDesc with no extra info. 119 // TODO: Rather than going through a GraphiteResourceKey, migrate to having a cache of samplers 120 // keyed off of SamplerDesc to minimize heap allocations. 121 virtual GraphiteResourceKey makeSamplerKey(const SamplerDesc& samplerDesc) const; 122 123 // Backends can optionally override this method to return meaningful sampler conversion info. 124 // By default, simply return a default ImmutableSamplerInfo. getImmutableSamplerInfo(sk_sp<TextureProxy> proxy)125 virtual ImmutableSamplerInfo getImmutableSamplerInfo(sk_sp<TextureProxy> proxy) const { 126 return {}; 127 } 128 extractGraphicsDescs(const UniqueKey &,GraphicsPipelineDesc *,RenderPassDesc *,const RendererProvider *)129 virtual bool extractGraphicsDescs(const UniqueKey&, 130 GraphicsPipelineDesc*, 131 RenderPassDesc*, 132 const RendererProvider*) const { return false; } 133 134 bool areColorTypeAndTextureInfoCompatible(SkColorType, const TextureInfo&) const; 135 virtual uint32_t channelMask(const TextureInfo&) const = 0; 136 137 bool isTexturable(const TextureInfo&) const; 138 virtual bool isRenderable(const TextureInfo&) const = 0; 139 virtual bool isStorage(const TextureInfo&) const = 0; 140 maxTextureSize()141 int maxTextureSize() const { return fMaxTextureSize; } defaultMSAASamplesCount()142 int defaultMSAASamplesCount() const { return fDefaultMSAASamples; } 143 144 virtual void buildKeyForTexture(SkISize dimensions, 145 const TextureInfo&, 146 ResourceType, 147 Shareable, 148 GraphiteResourceKey*) const = 0; 149 resourceBindingRequirements()150 const ResourceBindingRequirements& resourceBindingRequirements() const { 151 return fResourceBindingReqs; 152 } 153 154 // Returns the required alignment in bytes for the offset into a uniform buffer when binding it 155 // to a draw. requiredUniformBufferAlignment()156 size_t requiredUniformBufferAlignment() const { return fRequiredUniformBufferAlignment; } 157 158 // Returns the required alignment in bytes for the offset into a storage buffer when binding it 159 // to a draw. requiredStorageBufferAlignment()160 size_t requiredStorageBufferAlignment() const { return fRequiredStorageBufferAlignment; } 161 162 // Returns the required alignment in bytes for the offset and size of copies involving a buffer. requiredTransferBufferAlignment()163 size_t requiredTransferBufferAlignment() const { return fRequiredTransferBufferAlignment; } 164 165 // Returns the aligned rowBytes when transfering to or from a Texture getAlignedTextureDataRowBytes(size_t rowBytes)166 size_t getAlignedTextureDataRowBytes(size_t rowBytes) const { 167 return SkAlignTo(rowBytes, fTextureDataRowBytesAlignment); 168 } 169 170 /** 171 * Backends may have restrictions on what types of textures support Device::writePixels(). 172 * If this returns false then the caller should implement a fallback where a temporary texture 173 * is created, pixels are written to it, and then that is copied or drawn into the the surface. 174 */ 175 virtual bool supportsWritePixels(const TextureInfo& textureInfo) const = 0; 176 177 /** 178 * Backends may have restrictions on what types of textures support Device::readPixels(). 179 * If this returns false then the caller should implement a fallback where a temporary texture 180 * is created, the original texture is copied or drawn into it, and then pixels read from 181 * the temporary texture. 182 */ 183 virtual bool supportsReadPixels(const TextureInfo& textureInfo) const = 0; 184 185 /** 186 * Given a dst pixel config and a src color type what color type must the caller coax the 187 * the data into in order to use writePixels. 188 * 189 * We currently don't have an SkColorType for a 3 channel RGB format. Additionally the current 190 * implementation of raster pipeline requires power of 2 channels, so it is not easy to add such 191 * an SkColorType. Thus we need to check for data that is 3 channels using the isRGBFormat 192 * return value and handle it manually 193 */ 194 virtual std::pair<SkColorType, bool /*isRGB888Format*/> supportedWritePixelsColorType( 195 SkColorType dstColorType, 196 const TextureInfo& dstTextureInfo, 197 SkColorType srcColorType) const = 0; 198 199 /** 200 * Given a src surface's color type and its texture info as well as a color type the caller 201 * would like read into, this provides a legal color type that the caller can use for 202 * readPixels. The returned color type may differ from the passed dstColorType, in 203 * which case the caller must convert the read pixel data (see GrConvertPixels). When converting 204 * to dstColorType the swizzle in the returned struct should be applied. The caller must check 205 * the returned color type for kUnknown. 206 * 207 * We currently don't have an SkColorType for a 3 channel RGB format. Additionally the current 208 * implementation of raster pipeline requires power of 2 channels, so it is not easy to add such 209 * an SkColorType. Thus we need to check for data that is 3 channels using the isRGBFormat 210 * return value and handle it manually 211 */ 212 virtual std::pair<SkColorType, bool /*isRGBFormat*/> supportedReadPixelsColorType( 213 SkColorType srcColorType, 214 const TextureInfo& srcTextureInfo, 215 SkColorType dstColorType) const = 0; 216 217 /** 218 * Checks whether the passed color type is renderable. If so, the same color type is passed 219 * back. If not, provides an alternative (perhaps lower bit depth and/or unorm instead of float) 220 * color type that is supported or kUnknown if there no renderable fallback format. 221 */ 222 SkColorType getRenderableColorType(SkColorType) const; 223 clampToBorderSupport()224 bool clampToBorderSupport() const { return fClampToBorderSupport; } 225 protectedSupport()226 bool protectedSupport() const { return fProtectedSupport; } 227 228 // Supports BackendSemaphores semaphoreSupport()229 bool semaphoreSupport() const { return fSemaphoreSupport; } 230 231 // If false then calling Context::submit with SyncToCpu::kYes is an error. allowCpuSync()232 bool allowCpuSync() const { return fAllowCpuSync; } 233 234 // Returns whether storage buffers are supported. storageBufferSupport()235 bool storageBufferSupport() const { return fStorageBufferSupport; } 236 237 // Returns whether storage buffers are preferred over uniform buffers, when both will yield 238 // correct results. storageBufferPreferred()239 bool storageBufferPreferred() const { return fStorageBufferPreferred; } 240 241 // Returns whether a draw buffer can be mapped. drawBufferCanBeMapped()242 bool drawBufferCanBeMapped() const { return fDrawBufferCanBeMapped; } 243 244 #if defined(GRAPHITE_TEST_UTILS) drawBufferCanBeMappedForReadback()245 bool drawBufferCanBeMappedForReadback() const { return fDrawBufferCanBeMappedForReadback; } 246 #endif 247 248 // Returns whether using Buffer::asyncMap() must be used to map buffers. map() may only be 249 // called after asyncMap() is called and will fail if the asynchronous map is not complete. This 250 // excludes premapped buffers for which map() can be called freely until the first unmap() call. bufferMapsAreAsync()251 bool bufferMapsAreAsync() const { return fBufferMapsAreAsync; } 252 253 // Returns whether multisampled render to single sampled is supported. msaaRenderToSingleSampledSupport()254 bool msaaRenderToSingleSampledSupport() const { return fMSAARenderToSingleSampledSupport; } 255 256 // Returns whether compute shaders are supported. computeSupport()257 bool computeSupport() const { return fComputeSupport; } 258 259 /** 260 * Returns true if the given backend supports importing AHardwareBuffers. This will only 261 * ever be supported on Android devices with API level >= 26. 262 */ supportsAHardwareBufferImages()263 bool supportsAHardwareBufferImages() const { return fSupportsAHardwareBufferImages; } 264 265 // Returns the skgpu::Swizzle to use when sampling or reading back from a texture with the 266 // passed in SkColorType and TextureInfo. 267 skgpu::Swizzle getReadSwizzle(SkColorType, const TextureInfo&) const; 268 269 // Returns the skgpu::Swizzle to use when writing colors to a surface with the passed in 270 // SkColorType and TextureInfo. 271 skgpu::Swizzle getWriteSwizzle(SkColorType, const TextureInfo&) const; 272 shaderErrorHandler()273 skgpu::ShaderErrorHandler* shaderErrorHandler() const { return fShaderErrorHandler; } 274 275 // Returns what method of dst read is required for a draw using the dst color. 276 DstReadRequirement getDstReadRequirement() const; 277 minDistanceFieldFontSize()278 float minDistanceFieldFontSize() const { return fMinDistanceFieldFontSize; } glyphsAsPathsFontSize()279 float glyphsAsPathsFontSize() const { return fGlyphsAsPathsFontSize; } 280 glyphCacheTextureMaximumBytes()281 size_t glyphCacheTextureMaximumBytes() const { return fGlyphCacheTextureMaximumBytes; } maxPathAtlasTextureSize()282 int maxPathAtlasTextureSize() const { return fMaxPathAtlasTextureSize; } 283 allowMultipleAtlasTextures()284 bool allowMultipleAtlasTextures() const { return fAllowMultipleAtlasTextures; } supportBilerpFromGlyphAtlas()285 bool supportBilerpFromGlyphAtlas() const { return fSupportBilerpFromGlyphAtlas; } 286 requireOrderedRecordings()287 bool requireOrderedRecordings() const { return fRequireOrderedRecordings; } 288 289 // When uploading to a full compressed texture do we need to pad the size out to a multiple of 290 // the block width and height. fullCompressedUploadSizeMustAlignToBlockDims()291 bool fullCompressedUploadSizeMustAlignToBlockDims() const { 292 return fFullCompressedUploadSizeMustAlignToBlockDims; 293 } 294 295 sktext::gpu::SDFTControl getSDFTControl(bool useSDFTForSmallText) const; 296 setBackendLabels()297 bool setBackendLabels() const { return fSetBackendLabels; } 298 299 protected: 300 Caps(); 301 302 // Subclasses must call this at the end of their init method in order to do final processing on 303 // the caps. 304 void finishInitialization(const ContextOptions&); 305 306 #if defined(GRAPHITE_TEST_UTILS) setDeviceName(const char * n)307 void setDeviceName(const char* n) { 308 fDeviceName = n; 309 } 310 #endif 311 312 // There are only a few possible valid sample counts (1, 2, 4, 8, 16). So we can key on those 5 313 // options instead of the actual sample value. SamplesToKey(uint32_t numSamples)314 static inline uint32_t SamplesToKey(uint32_t numSamples) { 315 switch (numSamples) { 316 case 1: 317 return 0; 318 case 2: 319 return 1; 320 case 4: 321 return 2; 322 case 8: 323 return 3; 324 case 16: 325 return 4; 326 default: 327 SkUNREACHABLE; 328 } 329 } 330 331 // ColorTypeInfo for a specific format. Used in format tables. 332 struct ColorTypeInfo { 333 ColorTypeInfo() = default; ColorTypeInfoColorTypeInfo334 ColorTypeInfo(SkColorType ct, SkColorType transferCt, uint32_t flags, 335 skgpu::Swizzle readSwizzle, skgpu::Swizzle writeSwizzle) 336 : fColorType(ct) 337 , fTransferColorType(transferCt) 338 , fFlags(flags) 339 , fReadSwizzle(readSwizzle) 340 , fWriteSwizzle(writeSwizzle) {} 341 342 SkColorType fColorType = kUnknown_SkColorType; 343 SkColorType fTransferColorType = kUnknown_SkColorType; 344 enum { 345 kUploadData_Flag = 0x1, 346 // Does Graphite itself support rendering to this colorType & format pair. Renderability 347 // still additionally depends on if the format itself is renderable. 348 kRenderable_Flag = 0x2, 349 }; 350 uint32_t fFlags = 0; 351 352 skgpu::Swizzle fReadSwizzle; 353 skgpu::Swizzle fWriteSwizzle; 354 }; 355 356 int fMaxTextureSize = 0; 357 int fDefaultMSAASamples = 4; 358 size_t fRequiredUniformBufferAlignment = 0; 359 size_t fRequiredStorageBufferAlignment = 0; 360 size_t fRequiredTransferBufferAlignment = 0; 361 size_t fTextureDataRowBytesAlignment = 1; 362 363 std::unique_ptr<SkSL::ShaderCaps> fShaderCaps; 364 365 bool fClampToBorderSupport = true; 366 bool fProtectedSupport = false; 367 bool fSemaphoreSupport = false; 368 bool fAllowCpuSync = true; 369 bool fStorageBufferSupport = false; 370 bool fStorageBufferPreferred = false; 371 bool fDrawBufferCanBeMapped = true; 372 bool fBufferMapsAreAsync = false; 373 bool fMSAARenderToSingleSampledSupport = false; 374 375 bool fComputeSupport = false; 376 bool fSupportsAHardwareBufferImages = false; 377 bool fFullCompressedUploadSizeMustAlignToBlockDims = false; 378 379 #if defined(GRAPHITE_TEST_UTILS) 380 bool fDrawBufferCanBeMappedForReadback = true; 381 #endif 382 383 ResourceBindingRequirements fResourceBindingReqs; 384 385 ////////////////////////////////////////////////////////////////////////////////////////// 386 // Client-provided Caps 387 388 /** 389 * If present, use this object to report shader compilation failures. If not, report failures 390 * via SkDebugf and assert. 391 */ 392 ShaderErrorHandler* fShaderErrorHandler = nullptr; 393 394 #if defined(GRAPHITE_TEST_UTILS) 395 std::string fDeviceName; 396 int fMaxTextureAtlasSize = 2048; 397 PathRendererStrategy fRequestedPathRendererStrategy; 398 #endif 399 size_t fGlyphCacheTextureMaximumBytes = 2048 * 1024 * 4; 400 401 float fMinDistanceFieldFontSize = 18; 402 float fGlyphsAsPathsFontSize = 324; 403 404 int fMaxPathAtlasTextureSize = 8192; 405 406 bool fAllowMultipleAtlasTextures = true; 407 bool fSupportBilerpFromGlyphAtlas = false; 408 409 // Set based on client options 410 bool fRequireOrderedRecordings = false; 411 412 bool fSetBackendLabels = false; 413 414 private: 415 virtual bool onIsTexturable(const TextureInfo&) const = 0; 416 virtual const ColorTypeInfo* getColorTypeInfo(SkColorType, const TextureInfo&) const = 0; 417 418 sk_sp<SkCapabilities> fCapabilities; 419 }; 420 421 } // namespace skgpu::graphite 422 423 #endif // skgpu_graphite_Caps_DEFINED 424