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