| /* | |
| * Copyright 2021 Google LLC | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #ifndef skgpu_graphite_Caps_DEFINED | |
| #define skgpu_graphite_Caps_DEFINED | |
| #include "include/core/SkColorType.h" | |
| #include "include/core/SkRefCnt.h" | |
| #include "include/core/SkSize.h" | |
| #include "include/gpu/GpuTypes.h" | |
| #include "include/private/SkAlign.h" | |
| #include "include/private/SkAssert.h" | |
| #include "include/private/SkEnumBitMask.h" | |
| #include "src/core/SkSafeMath.h" | |
| #include "src/gpu/ResourceKey.h" | |
| #include "src/gpu/Swizzle.h" | |
| #include "src/gpu/graphite/ResourceTypes.h" | |
| #include "src/gpu/graphite/TextureFormat.h" | |
| #include "src/text/gpu/SubRunControl.h" | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <memory> | |
| #include <string> | |
| #include <string_view> | |
| #include <utility> | |
| class SkCapabilities; | |
| enum class SkTextureCompressionType; | |
| namespace SkSL { struct ShaderCaps; } | |
| namespace skgpu { class ShaderErrorHandler; } | |
| namespace skgpu::graphite { | |
| class ComputePipelineDesc; | |
| class GraphicsPipelineDesc; | |
| class GraphiteResourceKey; | |
| class RendererProvider; | |
| class TextureInfo; | |
| enum class DepthStencilFlags : int; | |
| enum class PathRendererStrategy; | |
| struct AttachmentDesc; | |
| struct ContextOptions; | |
| struct RenderPassDesc; | |
| struct ResourceBindingRequirements { | |
| /* The API of the backend currently in use. */ | |
| BackendApi fBackendApi = BackendApi::kUnsupported; | |
| /* The required data layout rules for the contents of a uniform buffer. */ | |
| Layout fUniformBufferLayout = Layout::kInvalid; | |
| /* The required data layout rules for the contents of a storage buffer. */ | |
| Layout fStorageBufferLayout = Layout::kInvalid; | |
| /** | |
| * Whether combined texture-sampler types are supported. Backends that do not support combined | |
| * image samplers (i.e. sampler2D) require a texture and sampler object to be bound separately | |
| * and their binding indices explicitly specified in the shader text. | |
| */ | |
| bool fSeparateTextureAndSamplerBinding = false; | |
| /** | |
| * Whether intrinsic constant information is stored as push constants (rather than normal UBO). | |
| * Currently only relevant or possibly true for Dawn or Vulkan. | |
| */ | |
| bool fUsePushConstantsForIntrinsicConstants = false; | |
| /** | |
| * Whether compute shader textures use separate index ranges from other resources (i.e. buffers) | |
| */ | |
| bool fComputeUsesDistinctIdxRangesForTextures = false; | |
| /** | |
| * Define set indices. We assume that even if textures and samplers must be bound separately, | |
| * they will still be contained within the same set/group. | |
| */ | |
| static constexpr int kUnassigned = -1; | |
| int fUniformsSetIdx = kUnassigned; | |
| int fTextureSamplerSetIdx = kUnassigned; | |
| int fInputAttachmentSetIdx = kUnassigned; | |
| /* Define uniform and storage buffer bindings */ | |
| int fIntrinsicBufferBinding = kUnassigned; | |
| int fCombinedUniformBufferBinding = kUnassigned; | |
| int fStorageBufferBinding = kUnassigned; | |
| /* Maximum texture atlas dimension for StorageBuffer fallback texture, defaults to 2048 */ | |
| static constexpr int kDefaultMaxFallbackTextureSize = 2048; | |
| // 128 MB is the minimum guaranteed storage buffer binding range across WebGPU/Dawn | |
| // (maxStorageBufferBindingSize) and Vulkan (maxStorageBufferRange). | |
| static constexpr int kDefaultMaxStorageBufferBytes = 128 * 1024 * 1024; | |
| int fMaxFallbackTextureSize = kUnassigned; | |
| int fMaxFallbackTextureBytes = kUnassigned; | |
| int fMaxStorageBufferBytes = kDefaultMaxStorageBufferBytes; | |
| }; | |
| class Caps { | |
| public: | |
| virtual ~Caps(); | |
| const SkSL::ShaderCaps* shaderCaps() const { return fShaderCaps.get(); } | |
| sk_sp<SkCapabilities> capabilities() const; | |
| #if defined(GPU_TEST_UTILS) | |
| std::string_view deviceName() const { return fDeviceName; } | |
| std::optional<PathRendererStrategy> requestedPathRendererStrategy() const { | |
| return fRequestedPathRendererStrategy; | |
| } | |
| #endif | |
| virtual UniqueKey makeGraphicsPipelineKey(const GraphicsPipelineDesc&, | |
| const RenderPassDesc&) const = 0; | |
| virtual UniqueKey makeComputePipelineKey(const ComputePipelineDesc&) const = 0; | |
| virtual bool extractGraphicsDescs(const UniqueKey&, | |
| GraphicsPipelineDesc*, | |
| RenderPassDesc*, | |
| const RendererProvider*) const { return false; } | |
| virtual bool loadOpAffectsMSAAPipelines() const { return false; } | |
| bool avoidMSAA() const { | |
| // Publicly, treat avoiding MSAA due to device issues or due to client option equivalently. | |
| return fAvoidMSAA || fMaxInternalSampleCount == SampleCount::k1 || fAvoidDepthMode; | |
| } | |
| bool avoidDepthMode() const { | |
| return fAvoidDepthMode; | |
| } | |
| /* Returns whether multisampled render to single sampled is supported. */ | |
| bool msaaRenderToSingleSampledSupport() const { return fMSAARenderToSingleSampledSupport; } | |
| // Sizing requirements for auxiliary attachments in a renderpass, such as the depth/stencil | |
| // or color MSAA attachment. | |
| enum class AttachmentSizePolicy : uint8_t { | |
| kExact, // Auxiliary attachments must have the exact same size as the main texture | |
| kApprox, // Auxiliary attachments can be made larger via GetApproxSize() | |
| kMSAARenderArea, // MSAA-only attachments can be made smaller to fit the render bounds | |
| }; | |
| /** | |
| * Returns whether a render pass's MSAA/depth/stencil attachments can have a different size | |
| * than the resolve attachment (or the single-sampled color attachment when there is no | |
| * MSAA involved). | |
| * | |
| * The MSAA attachment and the depth/stencil attachment must still match each other's size. | |
| * If partial load/resolve is not supported, all attachments (including the resolve attachment) | |
| * must still be larger than the framebuffer size. | |
| */ | |
| AttachmentSizePolicy attachmentSizePolicy() const { | |
| return fAttachmentSizePolicy; | |
| } | |
| /** | |
| * Get required depth attachment dimensions for a given color attachment info and dimensions. | |
| * This assumes `colorAttachmentDimensions` has already been adjusted for attachmentSizePolicy() | |
| * and this function's primary purpose is to handle complex requirements when rendering into | |
| * multiplanar texture views. | |
| */ | |
| virtual SkISize getDepthAttachmentDimensions(const TextureInfo&, | |
| const SkISize colorAttachmentDimensions) const { | |
| return colorAttachmentDimensions; | |
| } | |
| bool isSampleCountSupported(TextureFormat, SampleCount) const; | |
| /* Return the TextureFormat that satisfies `dsFlags`. */ | |
| TextureFormat getDepthStencilFormat(SkEnumBitMask<DepthStencilFlags>) const; | |
| TextureInfo getDefaultAttachmentTextureInfo(AttachmentDesc, | |
| Protected, | |
| Discardable) const; | |
| TextureInfo getDefaultSampledTextureInfo(SkColorType, | |
| Mipmapped, | |
| Protected, | |
| Renderable) const; | |
| TextureInfo getDefaultReadableTextureInfo(TextureFormat, | |
| Protected = Protected::kNo) const; | |
| TextureInfo getTextureInfoForSampledCopy(const TextureInfo&, Mipmapped) const; | |
| TextureInfo getTextureInfoForReadableCopy(const TextureInfo&) const; | |
| TextureInfo getDefaultCompressedTextureInfo(SkTextureCompressionType, | |
| Mipmapped, | |
| Protected) const; | |
| TextureInfo getDefaultStorageTextureInfo(SkColorType) const; | |
| TextureInfo getDefaultReadableStorageTextureInfo(TextureFormat, Protected) const; | |
| // Tries to return a sample count > 1 if needing MSAA to render into the target specification. | |
| // If the target is already multisampled, it will be that count; otherwise it will be the | |
| // highest supported sample count less than the configured max internal sample count. | |
| // | |
| // NOTE: If avoidMSAA() is true (either from ContextOptions or driver workarounds), the max | |
| // internal sample count is 1. In this case getCompatibleMSAASampleCount() returns k1 for single | |
| // sampled targets to show MSAA isn't supported. | |
| SampleCount getCompatibleMSAASampleCount(const TextureInfo&) const; | |
| // If true, the texture can be sampled within a shader with linear filtering. | |
| bool isTexturable(const TextureInfo&, bool allowMSAA=false) const; | |
| // If true, the texture can be read within a shader (via nearest sampling, texel fetch, | |
| // or as a readonly proxy for storage buffers). | |
| bool isReadable(const TextureInfo&, bool allowMSAA=false) const; | |
| // If true, the texture can be rasterized and/or resolved to (possibly with MSAA) | |
| bool isRenderable(const TextureInfo&) const; | |
| // If true, the texture can be rasterized using multisample-render-to-single-sample features. | |
| bool isRenderableWithMSRTSS(const TextureInfo&) const; | |
| // If true, the texture can be the source of data copied to another texture or to a buffer. | |
| // If false, the texture can only be copied via drawing (which requires isTexturable()). | |
| bool isCopyableSrc(const TextureInfo&) const; | |
| // If true, the texture can be the destination of data copied from another texture or buffer. | |
| // If false, the texture can only be updated by drawing (which requires isRenderable()). | |
| bool isCopyableDst(const TextureInfo&) const; | |
| // If true, the texture can be used as a storage texture in compute shaders. | |
| bool isStorage(const TextureInfo&) const; | |
| /** | |
| * Backends can optionally override this method to return meaningful sampler conversion info. | |
| * By default, simply return a default ImmutableSamplerInfo (e.g. no immutable sampler). | |
| */ | |
| virtual ImmutableSamplerInfo getImmutableSamplerInfo(const TextureInfo&) const { | |
| return {}; | |
| } | |
| /* Returns a compressed label describing the immutable sampler for the Pipeline label */ | |
| virtual std::string toString(const ImmutableSamplerInfo&) const { return ""; } | |
| // If true, uses experimental drawListLayer ordering. | |
| bool useDrawListLayer() const { return fDrawListLayer; } | |
| int maxTextureSize() const { return fMaxTextureSize; } | |
| virtual void buildKeyForTexture(SkISize dimensions, | |
| const TextureInfo&, | |
| ResourceType, | |
| GraphiteResourceKey*) const = 0; | |
| const ResourceBindingRequirements& resourceBindingRequirements() const { | |
| return fResourceBindingReqs; | |
| } | |
| /** | |
| * Returns the maximum number of varyings allowed in a render pipeline. Note that this is the | |
| * number of varying variables, not the total number of varying scalars. | |
| */ | |
| int maxVaryings() const { return fMaxVaryings; } | |
| /** | |
| * Returns the required alignment in bytes for the offset into a uniform buffer when binding it | |
| * to a draw. | |
| */ | |
| size_t requiredUniformBufferAlignment() const { return fRequiredUniformBufferAlignment; } | |
| /** | |
| * Returns the required alignment in bytes for the offset into a storage buffer when binding it | |
| * to a draw. | |
| */ | |
| size_t requiredStorageBufferAlignment() const { return fRequiredStorageBufferAlignment; } | |
| /** | |
| * Returns the required alignment in bytes for the offset and size of copies involving a buffer. | |
| */ | |
| size_t requiredTransferBufferAlignment() const { return fRequiredTransferBufferAlignment; } | |
| /* Returns the aligned rowBytes when transferring to or from a Texture */ | |
| size_t getAlignedTextureDataRowBytes(size_t rowBytes, size_t bytesPerBlock) const { | |
| SkASSERT(bytesPerBlock > 0); | |
| SkASSERT(fTextureDataRowBytesAlignment > 0); | |
| SkSafeMath safe; | |
| size_t alignment = safe.lcm(bytesPerBlock, fTextureDataRowBytesAlignment); | |
| size_t alignedRowBytes = safe.alignUpNonPow2(rowBytes, alignment); | |
| return safe.ok() ? alignedRowBytes : 0; | |
| } | |
| /** | |
| * When uploading to a full compressed texture do we need to pad the size out to a multiple of | |
| * the block width and height. | |
| */ | |
| bool fullCompressedUploadSizeMustAlignToBlockDims() const { | |
| return fFullCompressedUploadSizeMustAlignToBlockDims; | |
| } | |
| /** | |
| * Determines the orientation of the NDC coordinates emitted by the vertex stage relative to | |
| * both Skia's presumed top-left Y-down system and the viewport coordinates (which are also | |
| * always top-left, Y-down for all supported backends).) | |
| * | |
| * If true is returned, then (-1,-1) in normalized device coords maps to the top-left of the | |
| * configured viewport and positive Y points down. This aligns with Skia's conventions. | |
| * If false is returned, then (-1,-1) in NDC maps to the bottom-left of the viewport and | |
| * positive Y points up (so NDC is flipped relative to sk_Position and the viewport coords). | |
| * | |
| * There is no backend difference in handling the X axis so it's assumed -1 maps to the left | |
| * edge and +1 maps to the right edge. | |
| */ | |
| bool ndcYAxisPointsDown() const { return fNDCYAxisPointsDown; } | |
| bool clampToBorderSupport() const { return fClampToBorderSupport; } | |
| bool protectedSupport() const { return fProtectedSupport; } | |
| /* Supports BackendSemaphores */ | |
| bool semaphoreSupport() const { return fSemaphoreSupport; } | |
| /* If false then calling Context::submit with SyncToCpu::kYes is an error. */ | |
| bool allowCpuSync() const { return fAllowCpuSync; } | |
| /* Returns whether storage buffers are supported and to be preferred over uniform buffers. */ | |
| bool storageBufferSupport() const { | |
| SkASSERT(!fStorageBufferSupport || | |
| fResourceBindingReqs.fStorageBufferLayout == Layout::kStd430 || | |
| fResourceBindingReqs.fStorageBufferLayout == Layout::kStd430_F16 || | |
| fResourceBindingReqs.fStorageBufferLayout == Layout::kMetal); | |
| SkASSERT(fStorageBufferSupport || | |
| fResourceBindingReqs.fBackendApi != BackendApi::kMetal); | |
| return fStorageBufferSupport; | |
| } | |
| /* Returns whether storage buffers are supported for compute dispatches. */ | |
| bool storageBufferSupportForCompute() const { return fStorageBufferSupportForCompute; } | |
| /* Returns whether a draw buffer can be mapped. */ | |
| bool drawBufferCanBeMapped() const { return fDrawBufferCanBeMapped; } | |
| #if defined(GPU_TEST_UTILS) | |
| bool drawBufferCanBeMappedForReadback() const { return fDrawBufferCanBeMappedForReadback; } | |
| #endif | |
| /** | |
| * Returns whether using Buffer::asyncMap() must be used to map buffers. map() may only be | |
| * called after asyncMap() is called and will fail if the asynchronous map is not complete. This | |
| * excludes premapped buffers for which map() can be called freely until the first unmap() call. | |
| */ | |
| bool bufferMapsAreAsync() const { return fBufferMapsAreAsync; } | |
| /* Returns whether compute shaders are supported. */ | |
| bool computeSupport() const { return fComputeSupport; } | |
| /** | |
| * Returns true if the given backend supports importing AHardwareBuffers. This will only | |
| * ever be supported on Android devices with API level >= 26. | |
| */ | |
| bool supportsAHardwareBufferImages() const { return fSupportsAHardwareBufferImages; } | |
| /** | |
| * Enum representing the capabilities of the fixed function blend unit. | |
| */ | |
| enum BlendEquationSupport : uint8_t { | |
| kBasic = 0, /* Default bare minimum support. Allows selecting the operator that | |
| combines src + dst terms.*/ | |
| kAdvancedNoncoherent, /* Additional fixed function support for specific SVG/PDF blend modes. | |
| Requires blend barriers.*/ | |
| kAdvancedCoherent /* Advanced blend equation support that does not require blend | |
| barriers and permits overlap.*/ | |
| }; | |
| /** | |
| * Return the level of hardware advanced blend mode support. | |
| */ | |
| BlendEquationSupport blendEquationSupport() const { return fBlendEqSupport; } | |
| /** | |
| * Simple helper for indicating whether the hardware supports advanced blend modes at all | |
| * (coherent or noncoherent). | |
| */ | |
| bool supportsHardwareAdvancedBlending() const { | |
| return fBlendEqSupport > BlendEquationSupport::kBasic; | |
| } | |
| /** | |
| * Includes the following dynamic state: | |
| * | |
| * * Line width, depth bias, depth bounds, stencil compare mask, stencil write mask and stencil | |
| * reference. | |
| * This set corresponds to Vulkan 1.0 dynamic state. Blend constants does not depend on this | |
| * flag as it is always dynamic with all graphite backends. | |
| * | |
| * * Depth test enable, depth write enable, depth compare op, depth bounds test enable, depth | |
| * bias enable, stencil test enable and stencil op. | |
| * This set corresponds to depth and stencil related state from VK_EXT_extended_dynamic_state | |
| * and VK_EXT_extended_dynamic_state2. | |
| * | |
| * * Primitive topology and primitive restart enable. | |
| * Note that the primitive topology _class_ is not dynamic. | |
| * This set corresponds to input assembly state from VK_EXT_extended_dynamic_state and | |
| * VK_EXT_extended_dynamic_state2. | |
| * | |
| * * Cull mode, front face and rasterizer discard. | |
| * This set corresponds to rasterizer state from VK_EXT_extended_dynamic_state and | |
| * VK_EXT_extended_dynamic_state2. | |
| */ | |
| bool useBasicDynamicState() const { return fUseBasicDynamicState; } | |
| /** | |
| * Whether all vertex input state is dynamic. | |
| * This set corresponds to state from VK_EXT_vertex_input_dynamic_state. This state is | |
| * equivalently pulled out of the shaders pipeline via VK_EXT_graphics_pipeline_library | |
| * (usePipelineLibraries()). | |
| */ | |
| bool useVertexInputDynamicState() const { return fUseVertexInputDynamicState; } | |
| /** | |
| * Whether VK_EXT_graphics_pipeline_library should be used. In this case, the "shaders" subset | |
| * of the pipeline is compiled separately, then fast-linked with the vertex input and fragment | |
| * output state to create the final library. Currently, this is a detail of the Vulkan backend, | |
| * which helps VkPipelineCache hits (because the shaders pipeline hits the cache, and blend | |
| * state is patched in). However, this is most useful once exposed to the front-end, such that | |
| * it can track the (fewer) shaders pipeline separately, have the complete pipelines point to | |
| * the shaders pipeline, avoid unnecessary cache look ups, and more. (skbug.com/414645289) | |
| */ | |
| bool usePipelineLibraries() const { return fUsePipelineLibraries; } | |
| bool supportsHostImageCopy() const { return fSupportsHostImageCopy; } | |
| skgpu::ShaderErrorHandler* shaderErrorHandler() const { return fShaderErrorHandler; } | |
| /** | |
| * Returns what method of dst read a draw should use for obtaining the dst color. Backends can | |
| * use the default implementation or override this method as needed. | |
| */ | |
| virtual DstReadStrategy getDstReadStrategy() const; | |
| float minPathSizeForMSAA() const { return fMinMSAAPathSize; } | |
| float minDistanceFieldFontSize() const { return fMinDistanceFieldFontSize; } | |
| float glyphsAsPathsFontSize() const { return fGlyphsAsPathsFontSize; } | |
| size_t glyphCacheTextureMaximumBytes() const { return fGlyphCacheTextureMaximumBytes; } | |
| int maxPathAtlasTextureSize() const { return fMaxPathAtlasTextureSize; } | |
| bool allowMultipleAtlasTextures() const { return fAllowMultipleAtlasTextures; } | |
| bool supportBilerpFromGlyphAtlas() const { return fSupportBilerpFromGlyphAtlas; } | |
| bool requireOrderedRecordings() const { return fRequireOrderedRecordings; } | |
| sktext::gpu::SubRunControl getSubRunControl(bool useSDFTForSmallText) const; | |
| bool setBackendLabels() const { return fSetBackendLabels; } | |
| GpuStatsFlags supportedGpuStats() const { return fSupportedGpuStats; } | |
| protected: | |
| Caps(); | |
| // Initializes ShaderCaps to the baseline feature levels that Graphite assumes to be true. | |
| // Called in Caps' constructor so subclasses can override or set additional flags afterwards. | |
| void setDefaultShaderCaps(); | |
| /** | |
| * Subclasses must call this at the end of their init method in order to do final processing on | |
| * the caps. | |
| */ | |
| void finishInitialization(const ContextOptions&); | |
| #if defined(GPU_TEST_UTILS) | |
| void setDeviceName(std::string n) { | |
| fDeviceName = std::move(n); | |
| } | |
| #endif | |
| using FormatSupport = std::pair<SkEnumBitMask<TextureUsage>, SkEnumBitMask<SampleCount>>; | |
| // Indexed by Tiling then TextureFormat, must be filled out by subclasses during initialization. | |
| // This is zero-initialized so that every format defaults to unsupported unless a subclass | |
| // provides more information. | |
| std::array<std::array<FormatSupport, kTextureFormatCount>, 2> fFormatSupport{}; | |
| int fMaxTextureSize = 0; | |
| size_t fRequiredUniformBufferAlignment = 0; | |
| size_t fRequiredStorageBufferAlignment = 0; | |
| size_t fRequiredTransferBufferAlignment = 0; | |
| size_t fTextureDataRowBytesAlignment = 1; | |
| int fMaxVaryings = 0; | |
| std::unique_ptr<SkSL::ShaderCaps> fShaderCaps; | |
| bool fNDCYAxisPointsDown = false; // Most backends have NDC +Y pointing up | |
| bool fClampToBorderSupport = true; | |
| bool fProtectedSupport = false; | |
| bool fSemaphoreSupport = false; | |
| bool fAllowCpuSync = true; | |
| bool fStorageBufferSupport = false; | |
| bool fDrawBufferCanBeMapped = true; | |
| bool fBufferMapsAreAsync = false; | |
| bool fMSAARenderToSingleSampledSupport = false; | |
| bool fAvoidMSAA = false; | |
| bool fDrawListLayer = false; | |
| bool fAvoidDepthMode = false; | |
| bool fComputeSupport = false; | |
| bool fStorageBufferSupportForCompute = false; | |
| bool fSupportsAHardwareBufferImages = false; | |
| bool fFullCompressedUploadSizeMustAlignToBlockDims = false; | |
| // Dynamic state. The granularity is less fine than Vulkan's, but there is still some | |
| // granularity to allow for some dynamic state to be disabled due to driver bugs without having | |
| // to disable everything. Eventually, these can be used to create fewer pipelines in the first | |
| // place (b/414645289). | |
| bool fUseBasicDynamicState = false; | |
| bool fUseVertexInputDynamicState = false; | |
| bool fUsePipelineLibraries = false; | |
| // Whether it's possible to upload data to images using the CPU (host) instead of the device. | |
| // Under certain circumstances, it's more efficient to upload data in this way instead of | |
| // through a staging buffer. | |
| bool fSupportsHostImageCopy = false; | |
| #if defined(GPU_TEST_UTILS) | |
| bool fDrawBufferCanBeMappedForReadback = true; | |
| #endif | |
| ResourceBindingRequirements fResourceBindingReqs; | |
| BlendEquationSupport fBlendEqSupport = BlendEquationSupport::kBasic; | |
| AttachmentSizePolicy fAttachmentSizePolicy = AttachmentSizePolicy::kExact; | |
| GpuStatsFlags fSupportedGpuStats = GpuStatsFlags::kNone; | |
| ////////////////////////////////////////////////////////////////////////////////////////// | |
| // Client-provided Caps | |
| /** | |
| * If present, use this object to report shader compilation failures. If not, report failures | |
| * via SkDebugf and assert. | |
| */ | |
| ShaderErrorHandler* fShaderErrorHandler = nullptr; | |
| #if defined(GPU_TEST_UTILS) | |
| std::string fDeviceName; | |
| std::optional<PathRendererStrategy> fRequestedPathRendererStrategy; | |
| #endif | |
| // NOTE: This is a requested limit, the actual supported sample counts for a particular format | |
| // could be lower or higher. | |
| SampleCount fMaxInternalSampleCount = SampleCount::k4; | |
| size_t fGlyphCacheTextureMaximumBytes = 2048 * 1024 * 4; | |
| float fMinMSAAPathSize = 0; | |
| float fMinDistanceFieldFontSize = 18; | |
| float fGlyphsAsPathsFontSize = 324; | |
| int fMaxPathAtlasTextureSize = 8192; | |
| bool fAllowMultipleAtlasTextures = true; | |
| bool fSupportBilerpFromGlyphAtlas = false; | |
| bool fRequireOrderedRecordings = false; | |
| bool fSetBackendLabels = false; | |
| private: | |
| // Validates format support and calls onGetDefaultTextureInfo if it would be valid, returning | |
| // a TextureInfo for the first format that is supported. | |
| TextureInfo getDefaultTextureInfo(SkEnumBitMask<TextureUsage> usage, | |
| SkSpan<const TextureFormat>, | |
| SampleCount, | |
| Mipmapped, | |
| Protected, | |
| Discardable) const; | |
| // Return a TextureInfo that is configured to support the given usages with the requested format | |
| // and other properties. This is only called if getTextureSupport() matches for kOptimal tiling. | |
| virtual TextureInfo onGetDefaultTextureInfo(SkEnumBitMask<TextureUsage> usage, | |
| TextureFormat, | |
| SampleCount, | |
| Mipmapped, | |
| Protected, | |
| Discardable) const = 0; | |
| // Return the supported TextureUsages and SampleCounts for a texture of the given format and | |
| // tiling, assuming the textures are created with the requisite usages. | |
| FormatSupport getTextureSupport(TextureFormat format, Tiling tiling) const { | |
| return fFormatSupport[static_cast<int>(tiling)][static_cast<int>(format)]; | |
| } | |
| // Return the mask of TextureUsages supported by the described texture, as well as its tiling | |
| // representation. Subclasses can assume that this will only be called on valid TextureInfos | |
| // and do not need to account for TextureFormat supported features; Caps will combine the usage | |
| // and format support automatically. | |
| virtual std::pair<SkEnumBitMask<TextureUsage>, Tiling> getTextureUsage( | |
| const TextureInfo&) const = 0; | |
| // Returns true if the texture supports all usages in `test`, checking its declared usages | |
| // against its format's supported usages and its sample count against its format's supported | |
| // sample counts. | |
| // | |
| // `allowMSAA=false` forces false to be returned for any info with a sample count > 1. The other | |
| // allow flags are validation checks that are asserted against (and presumably implicit in the | |
| // usages that a format supports). | |
| bool isSupported(const TextureInfo&, | |
| SkEnumBitMask<TextureUsage> test, | |
| bool allowMSAA, | |
| bool allowExternal, | |
| bool allowCompressed, | |
| bool allowProtected) const; | |
| sk_sp<SkCapabilities> fCapabilities; | |
| }; | |
| } // namespace skgpu::graphite | |
| #endif // skgpu_graphite_Caps_DEFINED |