• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 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 GrVkCaps_DEFINED
9 #define GrVkCaps_DEFINED
10 
11 #include "include/gpu/vk/GrVkTypes.h"
12 #include "src/gpu/GrCaps.h"
13 
14 class GrVkExtensions;
15 struct GrVkInterface;
16 class GrVkRenderTarget;
17 
18 /**
19  * Stores some capabilities of a Vk backend.
20  */
21 class GrVkCaps : public GrCaps {
22 public:
23     /**
24      * Creates a GrVkCaps that is set such that nothing is supported. The init function should
25      * be called to fill out the caps.
26      */
27     GrVkCaps(const GrContextOptions& contextOptions,
28              const GrVkInterface* vkInterface,
29              VkPhysicalDevice device,
30              const VkPhysicalDeviceFeatures2& features,
31              uint32_t instanceVersion,
32              uint32_t physicalDeviceVersion,
33              const GrVkExtensions& extensions,
34              GrProtected isProtected = GrProtected::kNo);
35 
36     bool isFormatSRGB(const GrBackendFormat&) const override;
37 
38     bool isFormatTexturable(const GrBackendFormat&, GrTextureType) const override;
39     bool isVkFormatTexturable(VkFormat) const;
40 
isFormatCopyable(const GrBackendFormat &)41     bool isFormatCopyable(const GrBackendFormat&) const override { return true; }
42 
43     bool isFormatAsColorTypeRenderable(GrColorType ct,
44                                        const GrBackendFormat& format,
45                                        int sampleCount = 1) const override;
46     bool isFormatRenderable(const GrBackendFormat& format, int sampleCount) const override;
47     bool isFormatRenderable(VkFormat, int sampleCount) const;
48 
49     int getRenderTargetSampleCount(int requestedCount, const GrBackendFormat&) const override;
50     int getRenderTargetSampleCount(int requestedCount, VkFormat) const;
51 
52     int maxRenderTargetSampleCount(const GrBackendFormat&) const override;
53     int maxRenderTargetSampleCount(VkFormat format) const;
54 
55     SupportedWrite supportedWritePixelsColorType(GrColorType surfaceColorType,
56                                                  const GrBackendFormat& surfaceFormat,
57                                                  GrColorType srcColorType) const override;
58 
59     SurfaceReadPixelsSupport surfaceSupportsReadPixels(const GrSurface*) const override;
60 
isVkFormatTexturableLinearly(VkFormat format)61     bool isVkFormatTexturableLinearly(VkFormat format) const {
62         return SkToBool(FormatInfo::kTexturable_Flag & this->getFormatInfo(format).fLinearFlags);
63     }
64 
formatCanBeDstofBlit(VkFormat format,bool linearTiled)65     bool formatCanBeDstofBlit(VkFormat format, bool linearTiled) const {
66         const FormatInfo& info = this->getFormatInfo(format);
67         const uint16_t& flags = linearTiled ? info.fLinearFlags : info.fOptimalFlags;
68         return SkToBool(FormatInfo::kBlitDst_Flag & flags);
69     }
70 
formatCanBeSrcofBlit(VkFormat format,bool linearTiled)71     bool formatCanBeSrcofBlit(VkFormat format, bool linearTiled) const {
72         const FormatInfo& info = this->getFormatInfo(format);
73         const uint16_t& flags = linearTiled ? info.fLinearFlags : info.fOptimalFlags;
74         return SkToBool(FormatInfo::kBlitSrc_Flag & flags);
75     }
76 
77     // Gets the GrColorType that should be used to transfer data in/out of a transfer buffer to
78     // write/read data when using a VkFormat with a specified color type.
79     GrColorType transferColorType(VkFormat, GrColorType surfaceColorType) const;
80 
81     // On some GPUs (Windows Nvidia and Imagination) calls to QueueWaitIdle return before actually
82     // signalling the fences on the command buffers even though they have completed. This causes
83     // issues when then deleting the command buffers. Therefore we additionally will call
84     // vkWaitForFences on each outstanding command buffer to make sure the driver signals the fence.
mustSyncCommandBuffersWithQueue()85     bool mustSyncCommandBuffersWithQueue() const { return fMustSyncCommandBuffersWithQueue; }
86 
87     // Returns true if we should always make dedicated allocations for VkImages.
shouldAlwaysUseDedicatedImageMemory()88     bool shouldAlwaysUseDedicatedImageMemory() const {
89         return fShouldAlwaysUseDedicatedImageMemory;
90     }
91 
92     // Always use a transfer buffer instead of vkCmdUpdateBuffer to upload data to a VkBuffer.
avoidUpdateBuffers()93     bool avoidUpdateBuffers() const { return fAvoidUpdateBuffers; }
94 
95     /**
96      * Returns both a supported and most preferred stencil format to use in draws.
97      */
preferredStencilFormat()98     VkFormat preferredStencilFormat() const { return fPreferredStencilFormat; }
99 
100     // Returns total number of bits used by stencil + depth + padding
GetStencilFormatTotalBitCount(VkFormat format)101     static int GetStencilFormatTotalBitCount(VkFormat format) {
102         switch (format) {
103             case VK_FORMAT_S8_UINT:
104                 return 8;
105             case VK_FORMAT_D24_UNORM_S8_UINT:
106                 return 32;
107             case VK_FORMAT_D32_SFLOAT_S8_UINT:
108                 // can optionally have 24 unused bits at the end so we assume the total bits is 64.
109                 return 64;
110             default:
111                 SkASSERT(false);
112                 return 0;
113         }
114     }
115 
116     // Returns whether the device supports VK_KHR_Swapchain. Internally Skia never uses any of the
117     // swapchain functions, but we may need to transition to and from the
118     // VK_IMAGE_LAYOUT_PRESENT_SRC_KHR image layout, so we must know whether that layout is
119     // supported.
supportsSwapchain()120     bool supportsSwapchain() const { return fSupportsSwapchain; }
121 
122     // Returns whether the device supports the ability to extend VkPhysicalDeviceProperties struct.
supportsPhysicalDeviceProperties2()123     bool supportsPhysicalDeviceProperties2() const { return fSupportsPhysicalDeviceProperties2; }
124     // Returns whether the device supports the ability to extend VkMemoryRequirements struct.
supportsMemoryRequirements2()125     bool supportsMemoryRequirements2() const { return fSupportsMemoryRequirements2; }
126 
127     // Returns whether the device supports the ability to extend the vkBindMemory call.
supportsBindMemory2()128     bool supportsBindMemory2() const { return fSupportsBindMemory2; }
129 
130     // Returns whether or not the device suports the various API maintenance fixes to Vulkan 1.0. In
131     // Vulkan 1.1 all these maintenance are part of the core spec.
supportsMaintenance1()132     bool supportsMaintenance1() const { return fSupportsMaintenance1; }
supportsMaintenance2()133     bool supportsMaintenance2() const { return fSupportsMaintenance2; }
supportsMaintenance3()134     bool supportsMaintenance3() const { return fSupportsMaintenance3; }
135 
136     // Returns true if the device supports passing in a flag to say we are using dedicated GPU when
137     // allocating memory. For some devices this allows them to return more optimized memory knowning
138     // they will never need to suballocate amonst multiple objects.
supportsDedicatedAllocation()139     bool supportsDedicatedAllocation() const { return fSupportsDedicatedAllocation; }
140 
141     // Returns true if the device supports importing of external memory into Vulkan memory.
supportsExternalMemory()142     bool supportsExternalMemory() const { return fSupportsExternalMemory; }
143     // Returns true if the device supports importing Android hardware buffers into Vulkan memory.
supportsAndroidHWBExternalMemory()144     bool supportsAndroidHWBExternalMemory() const { return fSupportsAndroidHWBExternalMemory; }
145 
146     // Returns true if it supports ycbcr conversion for samplers
supportsYcbcrConversion()147     bool supportsYcbcrConversion() const { return fSupportsYcbcrConversion; }
148 
149     // Returns the number of descriptor slots used by immutable ycbcr VkImages.
150     //
151     // TODO: We should update this to return a count for a specific format or external format. We
152     // can use vkGetPhysicalDeviceImageFormatProperties2 with a
153     // VkSamplerYcbcrConversionImageFormatProperties to query this. However, right now that call
154     // does not support external android formats which is where the majority of ycbcr images are
155     // coming from. So for now we stay safe and always return 3 here which is the max value that the
156     // count could be for any format.
ycbcrCombinedImageSamplerDescriptorCount()157     uint32_t ycbcrCombinedImageSamplerDescriptorCount() const {
158         return 3;
159     }
160 
161     // Returns true if the device supports protected memory.
supportsProtectedMemory()162     bool supportsProtectedMemory() const { return fSupportsProtectedMemory; }
163 
164     // Returns true if the VK_EXT_image_drm_format_modifier is enabled.
supportsDRMFormatModifiers()165     bool supportsDRMFormatModifiers() const { return fSupportsDRMFormatModifiers; }
166 
167     // Returns whether we prefer to record draws directly into a primary command buffer.
preferPrimaryOverSecondaryCommandBuffers()168     bool preferPrimaryOverSecondaryCommandBuffers() const {
169         return fPreferPrimaryOverSecondaryCommandBuffers;
170     }
171 
maxPerPoolCachedSecondaryCommandBuffers()172     int maxPerPoolCachedSecondaryCommandBuffers() const {
173         return fMaxPerPoolCachedSecondaryCommandBuffers;
174     }
175 
maxInputAttachmentDescriptors()176     uint32_t maxInputAttachmentDescriptors() const { return fMaxInputAttachmentDescriptors; }
177 
mustInvalidatePrimaryCmdBufferStateAfterClearAttachments()178     bool mustInvalidatePrimaryCmdBufferStateAfterClearAttachments() const {
179         return fMustInvalidatePrimaryCmdBufferStateAfterClearAttachments;
180     }
181 
182     // For host visible allocations, this returns true if we require that they are coherent. This
183     // is used to work around bugs for devices that don't handle non-coherent memory correctly.
mustUseCoherentHostVisibleMemory()184     bool mustUseCoherentHostVisibleMemory() const { return fMustUseCoherentHostVisibleMemory; }
185 
186     // Returns whether a pure GPU accessible buffer is more performant to read than a buffer that is
187     // also host visible. If so then in some cases we may prefer the cost of doing a copy to the
188     // buffer. This typically would only be the case for buffers that are written once and read
189     // many times on the gpu.
gpuOnlyBuffersMorePerformant()190     bool gpuOnlyBuffersMorePerformant() const { return fGpuOnlyBuffersMorePerformant; }
191 
192     // For our CPU write and GPU read buffers (vertex, uniform, etc.), should we keep these buffers
193     // persistently mapped. In general the answer will be yes. The main case we don't do this is
194     // when using special memory that is DEVICE_LOCAL and HOST_VISIBLE on discrete GPUs.
shouldPersistentlyMapCpuToGpuBuffers()195     bool shouldPersistentlyMapCpuToGpuBuffers() const {
196         return fShouldPersistentlyMapCpuToGpuBuffers;
197     }
198 
199     // The max draw count that can be passed into indirect draw calls.
maxDrawIndirectDrawCount()200     uint32_t  maxDrawIndirectDrawCount() const { return fMaxDrawIndirectDrawCount; }
201 
202     /**
203      * Helpers used by canCopySurface. In all cases if the SampleCnt parameter is zero that means
204      * the surface is not a render target, otherwise it is the number of samples in the render
205      * target.
206      */
207     bool canCopyImage(VkFormat dstFormat,
208                       int dstSampleCnt,
209                       bool dstHasYcbcr,
210                       VkFormat srcFormat,
211                       int srcSamplecnt,
212                       bool srcHasYcbcr) const;
213 
214     bool canCopyAsBlit(VkFormat dstConfig,
215                        int dstSampleCnt,
216                        bool dstIsLinear,
217                        bool dstHasYcbcr,
218                        VkFormat srcConfig,
219                        int srcSampleCnt,
220                        bool srcIsLinear,
221                        bool srcHasYcbcr) const;
222 
223     bool canCopyAsResolve(VkFormat dstConfig,
224                           int dstSampleCnt,
225                           bool dstHasYcbcr,
226                           VkFormat srcConfig,
227                           int srcSamplecnt,
228                           bool srcHasYcbcr) const;
229 
230     GrBackendFormat getBackendFormatFromCompressionType(SkImage::CompressionType) const override;
231 
getFormatFromColorType(GrColorType colorType)232     VkFormat getFormatFromColorType(GrColorType colorType) const {
233         int idx = static_cast<int>(colorType);
234         return fColorTypeToFormatTable[idx];
235     }
236 
237     skgpu::Swizzle getWriteSwizzle(const GrBackendFormat&, GrColorType) const override;
238 
239     uint64_t computeFormatKey(const GrBackendFormat&) const override;
240 
241     int getFragmentUniformBinding() const;
242     int getFragmentUniformSet() const;
243 
244     void addExtraSamplerKey(skgpu::KeyBuilder*,
245                             GrSamplerState,
246                             const GrBackendFormat&) const override;
247 
248     GrProgramDesc makeDesc(GrRenderTarget*,
249                            const GrProgramInfo&,
250                            ProgramDescOverrideFlags) const override;
251 
252     GrInternalSurfaceFlags getExtraSurfaceFlagsForDeferredRT() const override;
253 
254     VkShaderStageFlags getPushConstantStageFlags() const;
255 
mustLoadFullImageWithDiscardableMSAA()256     bool mustLoadFullImageWithDiscardableMSAA() const {
257         return fMustLoadFullImageWithDiscardableMSAA;
258     }
supportsDiscardableMSAAForDMSAA()259     bool supportsDiscardableMSAAForDMSAA() const { return fSupportsDiscardableMSAAForDMSAA; }
260     bool renderTargetSupportsDiscardableMSAA(const GrVkRenderTarget*) const;
261     bool programInfoWillUseDiscardableMSAA(const GrProgramInfo&) const;
262 
dmsaaResolveCanBeUsedAsTextureInSameRenderPass()263     bool dmsaaResolveCanBeUsedAsTextureInSameRenderPass() const override { return false; }
264 
supportsMemorylessAttachments()265     bool supportsMemorylessAttachments() const { return fSupportsMemorylessAttachments; }
266 
267 #if GR_TEST_UTILS
268     std::vector<TestFormatColorTypeCombination> getTestingCombinations() const override;
269 #endif
270 
271 private:
272     enum VkVendor {
273         kAMD_VkVendor = 4098,
274         kARM_VkVendor = 5045,
275         kImagination_VkVendor = 4112,
276         kIntel_VkVendor = 32902,
277         kNvidia_VkVendor = 4318,
278         kQualcomm_VkVendor = 20803,
279     };
280 
281     // Some common Intel GPU models, currently we cover ICL/RKL/TGL/ADL
282     // Referenced from the following Mesa source files:
283     // https://github.com/mesa3d/mesa/blob/master/include/pci_ids/i965_pci_ids.h
284     // https://github.com/mesa3d/mesa/blob/master/include/pci_ids/iris_pci_ids.h
285     struct VkIntelGPUInfo {
286         // IceLake
287         const std::array<uint32_t, 14> IceLake = {
288             {0x8A50, 0x8A51, 0x8A52, 0x8A53, 0x8A54, 0x8A56, 0x8A57,
289              0x8A58, 0x8A59, 0x8A5A, 0x8A5B, 0x8A5C, 0x8A5D, 0x8A71}};
290         // RocketLake
291         const std::array<uint32_t, 5> RocketLake = {
292             {0x4c8a, 0x4c8b, 0x4c8c, 0x4c90, 0x4c9a}};
293         // TigerLake
294         const std::array<uint32_t, 11> TigerLake = {
295             {0x9A40, 0x9A49, 0x9A59, 0x9A60, 0x9A68, 0x9A70,
296              0x9A78, 0x9AC0, 0x9AC9, 0x9AD9, 0x9AF8}};
297         // Alderlake
298         const std::array<uint32_t, 10> Alderlake = {
299             {0x4680, 0x4681, 0x4682, 0x4683, 0x4690,
300              0x4691, 0x4692, 0x4693, 0x4698, 0x4699}};
301     };
302 
303     enum class VkIntelGPUType {
304         // 11th gen
305         kIntelIceLake,
306 
307         // 12th gen
308         kIntelRocketLake,
309         kIntelTigerLake,
310         kIntelAlderLake,
311 
312         kOther
313     };
314 
315     void init(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface,
316               VkPhysicalDevice device, const VkPhysicalDeviceFeatures2&,
317               uint32_t physicalDeviceVersion, const GrVkExtensions&, GrProtected isProtected);
318     void initGrCaps(const GrVkInterface* vkInterface,
319                     VkPhysicalDevice physDev,
320                     const VkPhysicalDeviceProperties&,
321                     const VkPhysicalDeviceMemoryProperties&,
322                     const VkPhysicalDeviceFeatures2&,
323                     const GrVkExtensions&);
324     void initShaderCaps(const VkPhysicalDeviceProperties&, const VkPhysicalDeviceFeatures2&);
325 
326     void initFormatTable(const GrVkInterface*, VkPhysicalDevice, const VkPhysicalDeviceProperties&);
327     void initStencilFormat(const GrVkInterface* iface, VkPhysicalDevice physDev);
328 
329     void applyDriverCorrectnessWorkarounds(const VkPhysicalDeviceProperties&);
330 
331     bool onSurfaceSupportsWritePixels(const GrSurface*) const override;
332     bool onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
333                           const SkIRect& srcRect, const SkIPoint& dstPoint) const override;
334     GrBackendFormat onGetDefaultBackendFormat(GrColorType) const override;
335 
336     bool onAreColorTypeAndFormatCompatible(GrColorType, const GrBackendFormat&) const override;
337 
338     SupportedRead onSupportedReadPixelsColorType(GrColorType, const GrBackendFormat&,
339                                                  GrColorType) const override;
340 
341     skgpu::Swizzle onGetReadSwizzle(const GrBackendFormat&, GrColorType) const override;
342 
343     GrDstSampleFlags onGetDstSampleFlagsForProxy(const GrRenderTargetProxy*) const override;
344 
345     bool onSupportsDynamicMSAA(const GrRenderTargetProxy*) const override;
346 
347     // ColorTypeInfo for a specific format
348     struct ColorTypeInfo {
349         GrColorType fColorType = GrColorType::kUnknown;
350         GrColorType fTransferColorType = GrColorType::kUnknown;
351         enum {
352             kUploadData_Flag = 0x1,
353             // Does Ganesh itself support rendering to this colorType & format pair. Renderability
354             // still additionally depends on if the format itself is renderable.
355             kRenderable_Flag = 0x2,
356             // Indicates that this colorType is supported only if we are wrapping a texture with
357             // the given format and colorType. We do not allow creation with this pair.
358             kWrappedOnly_Flag = 0x4,
359         };
360         uint32_t fFlags = 0;
361 
362         skgpu::Swizzle fReadSwizzle;
363         skgpu::Swizzle fWriteSwizzle;
364     };
365 
366     struct FormatInfo {
colorTypeFlagsFormatInfo367         uint32_t colorTypeFlags(GrColorType colorType) const {
368             for (int i = 0; i < fColorTypeInfoCount; ++i) {
369                 if (fColorTypeInfos[i].fColorType == colorType) {
370                     return fColorTypeInfos[i].fFlags;
371                 }
372             }
373             return 0;
374         }
375 
376         void init(const GrVkInterface*, VkPhysicalDevice, const VkPhysicalDeviceProperties&,
377                   VkFormat);
378         static void InitFormatFlags(VkFormatFeatureFlags, uint16_t* flags);
379         void initSampleCounts(const GrVkInterface*, VkPhysicalDevice,
380                               const VkPhysicalDeviceProperties&, VkFormat);
381 
382         enum {
383             kTexturable_Flag = 0x1,
384             kRenderable_Flag = 0x2,
385             kBlitSrc_Flag    = 0x4,
386             kBlitDst_Flag    = 0x8,
387         };
388 
389         uint16_t fOptimalFlags = 0;
390         uint16_t fLinearFlags = 0;
391 
392         SkTDArray<int> fColorSampleCounts;
393 
394         std::unique_ptr<ColorTypeInfo[]> fColorTypeInfos;
395         int fColorTypeInfoCount = 0;
396     };
397     static const size_t kNumVkFormats = 22;
398     FormatInfo fFormatTable[kNumVkFormats];
399 
400     FormatInfo& getFormatInfo(VkFormat);
401     const FormatInfo& getFormatInfo(VkFormat) const;
402 
403     VkFormat fColorTypeToFormatTable[kGrColorTypeCnt];
404     void setColorType(GrColorType, std::initializer_list<VkFormat> formats);
405 
406     VkFormat fPreferredStencilFormat;
407 
408     SkSTArray<1, GrVkYcbcrConversionInfo> fYcbcrInfos;
409 
410     bool fMustSyncCommandBuffersWithQueue = false;
411     bool fShouldAlwaysUseDedicatedImageMemory = false;
412 
413     bool fAvoidUpdateBuffers = false;
414 
415     bool fSupportsSwapchain = false;
416 
417     bool fSupportsPhysicalDeviceProperties2 = false;
418     bool fSupportsMemoryRequirements2 = false;
419     bool fSupportsBindMemory2 = false;
420     bool fSupportsMaintenance1 = false;
421     bool fSupportsMaintenance2 = false;
422     bool fSupportsMaintenance3 = false;
423 
424     bool fSupportsDedicatedAllocation = false;
425     bool fSupportsExternalMemory = false;
426     bool fSupportsAndroidHWBExternalMemory = false;
427 
428     bool fSupportsYcbcrConversion = false;
429 
430     bool fSupportsProtectedMemory = false;
431 
432     bool fSupportsDRMFormatModifiers = false;
433 
434     bool fPreferPrimaryOverSecondaryCommandBuffers = true;
435     bool fMustInvalidatePrimaryCmdBufferStateAfterClearAttachments = false;
436 
437     bool fMustUseCoherentHostVisibleMemory = false;
438     bool fGpuOnlyBuffersMorePerformant = false;
439     bool fShouldPersistentlyMapCpuToGpuBuffers = true;
440 
441     // We default this to 100 since we already cap the max render tasks at 100 before doing a
442     // submission in the GrDrawingManager, so we shouldn't be going over 100 secondary command
443     // buffers per primary anyways.
444     int fMaxPerPoolCachedSecondaryCommandBuffers = 100;
445 
446     uint32_t fMaxInputAttachmentDescriptors = 0;
447 
448     bool fMustLoadFullImageWithDiscardableMSAA = false;
449     bool fSupportsDiscardableMSAAForDMSAA = true;
450     bool fSupportsMemorylessAttachments = false;
451 
452     uint32_t fMaxDrawIndirectDrawCount = 0;
453 
454     using INHERITED = GrCaps;
455 };
456 
457 #endif
458