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