xref: /aosp_15_r20/external/skia/src/gpu/graphite/vk/VulkanCaps.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2022 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_VulkanCaps_DEFINED
9 #define skgpu_graphite_VulkanCaps_DEFINED
10 
11 #include "include/private/base/SkTDArray.h"
12 #include "src/gpu/graphite/Caps.h"
13 #include "src/gpu/vk/VulkanInterface.h"
14 #include "src/gpu/vk/VulkanUtilsPriv.h"
15 
16 namespace skgpu::graphite {
17 struct ContextOptions;
18 struct VulkanTextureInfo;
19 
20 class VulkanCaps final : public Caps {
21 public:
22     VulkanCaps(const ContextOptions&,
23                const skgpu::VulkanInterface*,
24                VkPhysicalDevice,
25                uint32_t physicalDeviceVersion,
26                const VkPhysicalDeviceFeatures2*,
27                const skgpu::VulkanExtensions*,
28                Protected);
29     ~VulkanCaps() override;
30 
31     TextureInfo getDefaultSampledTextureInfo(SkColorType,
32                                              Mipmapped mipmapped,
33                                              Protected,
34                                              Renderable) const override;
35 
36     TextureInfo getTextureInfoForSampledCopy(const TextureInfo& textureInfo,
37                                              Mipmapped mipmapped) const override;
38 
39     TextureInfo getDefaultCompressedTextureInfo(SkTextureCompressionType,
40                                                 Mipmapped mipmapped,
41                                                 Protected) const override;
42 
43     TextureInfo getDefaultMSAATextureInfo(const TextureInfo& singleSampledInfo,
44                                           Discardable discardable) const override;
45 
46     TextureInfo getDefaultDepthStencilTextureInfo(SkEnumBitMask<DepthStencilFlags>,
47                                                   uint32_t sampleCount,
48                                                   Protected) const override;
49 
50     TextureInfo getDefaultStorageTextureInfo(SkColorType) const override;
51 
52     ImmutableSamplerInfo getImmutableSamplerInfo(const TextureProxy* proxy) const override;
53 
54     UniqueKey makeGraphicsPipelineKey(const GraphicsPipelineDesc&,
55                                       const RenderPassDesc&) const override;
makeComputePipelineKey(const ComputePipelineDesc &)56     UniqueKey makeComputePipelineKey(const ComputePipelineDesc&) const override { return {}; }
57 
58     GraphiteResourceKey makeSamplerKey(const SamplerDesc&) const override;
59 
60     uint32_t channelMask(const TextureInfo&) const override;
61 
62     bool isTexturable(const VulkanTextureInfo&) const;
63 
64     bool isRenderable(const TextureInfo&) const override;
65     bool isRenderable(const VulkanTextureInfo&) const;
66     bool isStorage(const TextureInfo&) const override;
67 
68     void buildKeyForTexture(SkISize dimensions,
69                             const TextureInfo&,
70                             ResourceType,
71                             Shareable,
72                             GraphiteResourceKey*) const override;
73 
shouldAlwaysUseDedicatedImageMemory()74     bool shouldAlwaysUseDedicatedImageMemory() const {
75         return fShouldAlwaysUseDedicatedImageMemory;
76     }
77 
78     // Returns whether a pure GPU accessible buffer is more performant to read than a buffer that is
79     // also host visible. If so then in some cases we may prefer the cost of doing a copy to the
80     // buffer. This typically would only be the case for buffers that are written once and read
81     // many times on the gpu.
gpuOnlyBuffersMorePerformant()82     bool gpuOnlyBuffersMorePerformant() const { return fGpuOnlyBuffersMorePerformant; }
83 
84     // For our CPU write and GPU read buffers (vertex, uniform, etc.), we should keep these buffers
85     // persistently mapped. In general, the answer will be yes. The main case where we don't do this
86     // is when using special memory that is DEVICE_LOCAL and HOST_VISIBLE on discrete GPUs.
shouldPersistentlyMapCpuToGpuBuffers()87     bool shouldPersistentlyMapCpuToGpuBuffers() const {
88         return fShouldPersistentlyMapCpuToGpuBuffers;
89     }
90 
supportsYcbcrConversion()91     bool supportsYcbcrConversion() const { return fSupportsYcbcrConversion; }
92 
supportsDeviceFaultInfo()93     bool supportsDeviceFaultInfo() const { return fSupportsDeviceFaultInfo; }
94 
maxVertexAttributes()95     uint32_t maxVertexAttributes() const {
96         return fMaxVertexAttributes;
97     }
maxUniformBufferRange()98     uint64_t maxUniformBufferRange() const { return fMaxUniformBufferRange; }
99 
maxStorageBufferRange()100     uint64_t maxStorageBufferRange() const { return fMaxStorageBufferRange; }
101 
physicalDeviceMemoryProperties2()102     const VkPhysicalDeviceMemoryProperties2& physicalDeviceMemoryProperties2() const {
103         return fPhysicalDeviceMemoryProperties2;
104     }
105 
106     bool isTransferSrc(const VulkanTextureInfo&) const;
107     bool isTransferDst(const VulkanTextureInfo&) const;
108 
mustLoadFullImageForMSAA()109     bool mustLoadFullImageForMSAA() const { return fMustLoadFullImageForMSAA; }
110 
111 private:
112     enum VkVendor {
113         kAMD_VkVendor             = 4098,
114         kARM_VkVendor             = 5045,
115         kImagination_VkVendor     = 4112,
116         kIntel_VkVendor           = 32902,
117         kNvidia_VkVendor          = 4318,
118         kQualcomm_VkVendor        = 20803,
119     };
120 
121     void init(const ContextOptions&,
122               const skgpu::VulkanInterface*,
123               VkPhysicalDevice,
124               uint32_t physicalDeviceVersion,
125               const VkPhysicalDeviceFeatures2*,
126               const skgpu::VulkanExtensions*,
127               Protected);
128 
129     void applyDriverCorrectnessWorkarounds(const VkPhysicalDeviceProperties&);
130 
131     void initFormatTable(const skgpu::VulkanInterface*,
132                          VkPhysicalDevice,
133                          const VkPhysicalDeviceProperties&);
134 
135     void initDepthStencilFormatTable(const skgpu::VulkanInterface*,
136                                      VkPhysicalDevice,
137                                      const VkPhysicalDeviceProperties&);
138 
139     const ColorTypeInfo* getColorTypeInfo(SkColorType, const TextureInfo&) const override;
140 
141     bool onIsTexturable(const TextureInfo&) const override;
142 
143     bool supportsWritePixels(const TextureInfo&) const override;
144     bool supportsReadPixels(const TextureInfo&) const override;
145 
146     std::pair<SkColorType, bool /*isRGBFormat*/> supportedWritePixelsColorType(
147             SkColorType dstColorType,
148             const TextureInfo& dstTextureInfo,
149             SkColorType srcColorType) const override;
150     std::pair<SkColorType, bool /*isRGBFormat*/> supportedReadPixelsColorType(
151             SkColorType srcColorType,
152             const TextureInfo& srcTextureInfo,
153             SkColorType dstColorType) const override;
154 
155     // Struct that determines and stores which sample count quantities a VkFormat supports.
156     struct SupportedSampleCounts {
157         void initSampleCounts(const skgpu::VulkanInterface*,
158                               VkPhysicalDevice,
159                               const VkPhysicalDeviceProperties&,
160                               VkFormat,
161                               VkImageUsageFlags);
162 
163         bool isSampleCountSupported(int requestedCount) const;
164 
165         SkTDArray<int> fSampleCounts;
166     };
167 
168     // Struct that determines and stores useful information about VkFormats.
169     struct FormatInfo {
colorTypeFlagsFormatInfo170         uint32_t colorTypeFlags(SkColorType colorType) const {
171             for (int i = 0; i < fColorTypeInfoCount; ++i) {
172                 if (fColorTypeInfos[i].fColorType == colorType) {
173                     return fColorTypeInfos[i].fFlags;
174                 }
175             }
176             return 0;
177         }
178 
179         void init(const skgpu::VulkanInterface*,
180                   VkPhysicalDevice,
181                   const VkPhysicalDeviceProperties&,
182                   VkFormat);
183 
184         bool isTexturable(VkImageTiling) const;
185         bool isRenderable(VkImageTiling, uint32_t sampleCount) const;
186         bool isStorage(VkImageTiling) const;
187         bool isTransferSrc(VkImageTiling) const;
188         bool isTransferDst(VkImageTiling) const;
189 
190         std::unique_ptr<ColorTypeInfo[]> fColorTypeInfos;
191         int fColorTypeInfoCount = 0;
192 
193         VkFormatProperties fFormatProperties;
194         SupportedSampleCounts fSupportedSampleCounts;
195 
196         // Indicates that a format is only supported if we are wrapping a texture with it.
197         SkDEBUGCODE(bool fIsWrappedOnly = false;)
198     };
199 
200     // Map SkColorType to VkFormat.
201     VkFormat fColorTypeToFormatTable[kSkColorTypeCnt];
202     void setColorType(SkColorType, std::initializer_list<VkFormat> formats);
203     VkFormat getFormatFromColorType(SkColorType) const;
204 
205     // Map VkFormat to FormatInfo.
206     static const size_t kNumVkFormats = 22;
207     FormatInfo fFormatTable[kNumVkFormats];
208 
209     FormatInfo& getFormatInfo(VkFormat);
210     const FormatInfo& getFormatInfo(VkFormat) const;
211 
212     // A more lightweight equivalent to FormatInfo for depth/stencil VkFormats.
213     struct DepthStencilFormatInfo {
214         void init(const skgpu::VulkanInterface*,
215                   VkPhysicalDevice,
216                   const VkPhysicalDeviceProperties&,
217                   VkFormat);
218         bool isDepthStencilSupported(VkFormatFeatureFlags) const;
219 
220         VkFormatProperties fFormatProperties;
221         SupportedSampleCounts fSupportedSampleCounts;
222     };
223 
224     // Map DepthStencilFlags to VkFormat.
225     static const size_t kNumDepthStencilFlags = 4;
226     VkFormat fDepthStencilFlagsToFormatTable[kNumDepthStencilFlags];
227     VkFormat getFormatFromDepthStencilFlags(const SkEnumBitMask<DepthStencilFlags>& flags) const;
228 
229     // Map depth/stencil VkFormats to DepthStencilFormatInfo.
230     static const size_t kNumDepthStencilVkFormats = 5;
231     DepthStencilFormatInfo fDepthStencilFormatTable[kNumDepthStencilVkFormats];
232 
233     DepthStencilFormatInfo& getDepthStencilFormatInfo(VkFormat);
234     const DepthStencilFormatInfo& getDepthStencilFormatInfo(VkFormat) const;
235 
236     uint32_t fMaxVertexAttributes;
237     uint64_t fMaxUniformBufferRange;
238     uint64_t fMaxStorageBufferRange;
239     VkPhysicalDeviceMemoryProperties2 fPhysicalDeviceMemoryProperties2;
240 
241     // ColorTypeInfo struct for use w/ external formats.
242     const ColorTypeInfo fExternalFormatColorTypeInfo = {SkColorType::kRGBA_8888_SkColorType,
243                                                         SkColorType::kRGBA_8888_SkColorType,
244                                                         /*flags=*/0,
245                                                         skgpu::Swizzle::RGBA(),
246                                                         skgpu::Swizzle::RGBA()};
247 
248     // Various bools to define whether certain Vulkan features are supported.
249     bool fSupportsMemorylessAttachments = false;
250     bool fSupportsYcbcrConversion = false;
251     bool fShouldAlwaysUseDedicatedImageMemory = false;
252     bool fGpuOnlyBuffersMorePerformant = false;
253     bool fShouldPersistentlyMapCpuToGpuBuffers = true;
254     bool fSupportsDeviceFaultInfo = false;
255 
256     // Flags to enable workarounds for driver bugs
257     bool fMustLoadFullImageForMSAA = false;
258 };
259 
260 } // namespace skgpu::graphite
261 
262 #endif // skgpu_graphite_VulkanCaps_DEFINED
263