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 #include "src/gpu/vk/GrVkAttachment.h"
14 
15 class GrShaderCaps;
16 class GrVkExtensions;
17 struct GrVkInterface;
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, const GrVkInterface* vkInterface,
29              VkPhysicalDevice device, const VkPhysicalDeviceFeatures2& features,
30              uint32_t instanceVersion, uint32_t physicalDeviceVersion,
31              const GrVkExtensions& extensions, GrProtected isProtected = GrProtected::kNo);
32 
33     bool isFormatSRGB(const GrBackendFormat&) const override;
34 
35     bool isFormatTexturable(const GrBackendFormat&) const override;
36     bool isVkFormatTexturable(VkFormat) const;
37 
isFormatCopyable(const GrBackendFormat &)38     bool isFormatCopyable(const GrBackendFormat&) const override { return true; }
39 
40     bool isFormatAsColorTypeRenderable(GrColorType ct, const GrBackendFormat& format,
41                                        int sampleCount = 1) const override;
42     bool isFormatRenderable(const GrBackendFormat& format, int sampleCount) const override;
43     bool isFormatRenderable(VkFormat, int sampleCount) const;
44 
45     int getRenderTargetSampleCount(int requestedCount, const GrBackendFormat&) const override;
46     int getRenderTargetSampleCount(int requestedCount, VkFormat) const;
47 
48     int maxRenderTargetSampleCount(const GrBackendFormat&) const override;
49     int maxRenderTargetSampleCount(VkFormat format) const;
50 
51     SupportedWrite supportedWritePixelsColorType(GrColorType surfaceColorType,
52                                                  const GrBackendFormat& surfaceFormat,
53                                                  GrColorType srcColorType) const override;
54 
55     SurfaceReadPixelsSupport surfaceSupportsReadPixels(const GrSurface*) const override;
56 
isVkFormatTexturableLinearly(VkFormat format)57     bool isVkFormatTexturableLinearly(VkFormat format) const {
58         return SkToBool(FormatInfo::kTexturable_Flag & this->getFormatInfo(format).fLinearFlags);
59     }
60 
formatCanBeDstofBlit(VkFormat format,bool linearTiled)61     bool formatCanBeDstofBlit(VkFormat format, bool linearTiled) const {
62         const FormatInfo& info = this->getFormatInfo(format);
63         const uint16_t& flags = linearTiled ? info.fLinearFlags : info.fOptimalFlags;
64         return SkToBool(FormatInfo::kBlitDst_Flag & flags);
65     }
66 
formatCanBeSrcofBlit(VkFormat format,bool linearTiled)67     bool formatCanBeSrcofBlit(VkFormat format, bool linearTiled) const {
68         const FormatInfo& info = this->getFormatInfo(format);
69         const uint16_t& flags = linearTiled ? info.fLinearFlags : info.fOptimalFlags;
70         return SkToBool(FormatInfo::kBlitSrc_Flag & flags);
71     }
72 
73     // Sometimes calls to QueueWaitIdle return before actually signalling the fences
74     // on the command buffers even though they have completed. This causes an assert to fire when
75     // destroying the command buffers. Therefore we add a sleep to make sure the fence signals.
mustSleepOnTearDown()76     bool mustSleepOnTearDown() const {
77         return fMustSleepOnTearDown;
78     }
79 
80     // Returns true if we should always make dedicated allocations for VkImages.
shouldAlwaysUseDedicatedImageMemory()81     bool shouldAlwaysUseDedicatedImageMemory() const {
82         return fShouldAlwaysUseDedicatedImageMemory;
83     }
84 
85     // Always use a transfer buffer instead of vkCmdUpdateBuffer to upload data to a VkBuffer.
avoidUpdateBuffers()86     bool avoidUpdateBuffers() const {
87         return fAvoidUpdateBuffers;
88     }
89 
90     /**
91      * Returns both a supported and most preferred stencil format to use in draws.
92      */
preferredStencilFormat()93     VkFormat preferredStencilFormat() const {
94         return fPreferredStencilFormat;
95     }
96 
97     // Returns total number of bits used by stencil + depth + padding
GetStencilFormatTotalBitCount(VkFormat format)98     static int GetStencilFormatTotalBitCount(VkFormat format) {
99         switch (format) {
100         case VK_FORMAT_S8_UINT:
101             return 8;
102         case VK_FORMAT_D24_UNORM_S8_UINT:
103             return 32;
104         case VK_FORMAT_D32_SFLOAT_S8_UINT:
105             // can optionally have 24 unused bits at the end so we assume the total bits is 64.
106             return 64;
107         default:
108             SkASSERT(false);
109             return 0;
110         }
111     }
112 
113     // Returns whether the device supports VK_KHR_Swapchain. Internally Skia never uses any of the
114     // swapchain functions, but we may need to transition to and from the
115     // VK_IMAGE_LAYOUT_PRESENT_SRC_KHR image layout, so we must know whether that layout is
116     // supported.
supportsSwapchain()117     bool supportsSwapchain() const { return fSupportsSwapchain; }
118 
119     // Returns whether the device supports the ability to extend VkPhysicalDeviceProperties struct.
supportsPhysicalDeviceProperties2()120     bool supportsPhysicalDeviceProperties2() const { return fSupportsPhysicalDeviceProperties2; }
121     // Returns whether the device supports the ability to extend VkMemoryRequirements struct.
supportsMemoryRequirements2()122     bool supportsMemoryRequirements2() const { return fSupportsMemoryRequirements2; }
123 
124     // Returns whether the device supports the ability to extend the vkBindMemory call.
supportsBindMemory2()125     bool supportsBindMemory2() const { return fSupportsBindMemory2; }
126 
127     // Returns whether or not the device suports the various API maintenance fixes to Vulkan 1.0. In
128     // Vulkan 1.1 all these maintenance are part of the core spec.
supportsMaintenance1()129     bool supportsMaintenance1() const { return fSupportsMaintenance1; }
supportsMaintenance2()130     bool supportsMaintenance2() const { return fSupportsMaintenance2; }
supportsMaintenance3()131     bool supportsMaintenance3() const { return fSupportsMaintenance3; }
132 
133     // Returns true if the device supports passing in a flag to say we are using dedicated GPU when
134     // allocating memory. For some devices this allows them to return more optimized memory knowning
135     // they will never need to suballocate amonst multiple objects.
supportsDedicatedAllocation()136     bool supportsDedicatedAllocation() const { return fSupportsDedicatedAllocation; }
137 
138     // Returns true if the device supports importing of external memory into Vulkan memory.
supportsExternalMemory()139     bool supportsExternalMemory() const { return fSupportsExternalMemory; }
140     // Returns true if the device supports importing Android hardware buffers into Vulkan memory.
supportsAndroidHWBExternalMemory()141     bool supportsAndroidHWBExternalMemory() const { return fSupportsAndroidHWBExternalMemory; }
142 
143     // Returns true if it supports ycbcr conversion for samplers
supportsYcbcrConversion()144     bool supportsYcbcrConversion() const { return fSupportsYcbcrConversion; }
145 
146     // Returns true if the device supports protected memory.
supportsProtectedMemory()147     bool supportsProtectedMemory() const { return fSupportsProtectedMemory; }
148 
149     // Returns whether we prefer to record draws directly into a primary command buffer.
preferPrimaryOverSecondaryCommandBuffers()150     bool preferPrimaryOverSecondaryCommandBuffers() const {
151         return fPreferPrimaryOverSecondaryCommandBuffers;
152     }
153 
maxPerPoolCachedSecondaryCommandBuffers()154     int maxPerPoolCachedSecondaryCommandBuffers() const {
155         return fMaxPerPoolCachedSecondaryCommandBuffers;
156     }
157 
maxInputAttachmentDescriptors()158     uint32_t maxInputAttachmentDescriptors() const { return fMaxInputAttachmentDescriptors; }
159 
preferCachedCpuMemory()160     bool preferCachedCpuMemory() const { return fPreferCachedCpuMemory; }
161 
mustInvalidatePrimaryCmdBufferStateAfterClearAttachments()162     bool mustInvalidatePrimaryCmdBufferStateAfterClearAttachments() const {
163         return fMustInvalidatePrimaryCmdBufferStateAfterClearAttachments;
164     }
165 
166     /**
167      * Helpers used by canCopySurface. In all cases if the SampleCnt parameter is zero that means
168      * the surface is not a render target, otherwise it is the number of samples in the render
169      * target.
170      */
171     bool canCopyImage(VkFormat dstFormat, int dstSampleCnt, bool dstHasYcbcr,
172                       VkFormat srcFormat, int srcSamplecnt, bool srcHasYcbcr) const;
173 
174     bool canCopyAsBlit(VkFormat dstConfig, int dstSampleCnt, bool dstIsLinear, bool dstHasYcbcr,
175                        VkFormat srcConfig, int srcSampleCnt, bool srcIsLinear,
176                        bool srcHasYcbcr) const;
177 
178     bool canCopyAsResolve(VkFormat dstConfig, int dstSampleCnt, bool dstHasYcbcr,
179                           VkFormat srcConfig, int srcSamplecnt, bool srcHasYcbcr) const;
180 
181     GrBackendFormat getBackendFormatFromCompressionType(SkImage::CompressionType) const override;
182 
getFormatFromColorType(GrColorType colorType)183     VkFormat getFormatFromColorType(GrColorType colorType) const {
184         int idx = static_cast<int>(colorType);
185         return fColorTypeToFormatTable[idx];
186     }
187 
188     GrSwizzle getWriteSwizzle(const GrBackendFormat&, GrColorType) const override;
189 
190     uint64_t computeFormatKey(const GrBackendFormat&) const override;
191 
192     int getFragmentUniformBinding() const;
193     int getFragmentUniformSet() const;
194 
195     void addExtraSamplerKey(GrProcessorKeyBuilder*,
196                             GrSamplerState,
197                             const GrBackendFormat&) const override;
198 
199     GrProgramDesc makeDesc(GrRenderTarget*, const GrProgramInfo&) const override;
200 
201     GrInternalSurfaceFlags getExtraSurfaceFlagsForDeferredRT() const override;
202 
203 #if GR_TEST_UTILS
204     std::vector<TestFormatColorTypeCombination> getTestingCombinations() const override;
205 #endif
206 
207 private:
208     enum VkVendor {
209         kAMD_VkVendor = 4098,
210         kARM_VkVendor = 5045,
211         kImagination_VkVendor = 4112,
212         kIntel_VkVendor = 32902,
213         kNvidia_VkVendor = 4318,
214         kQualcomm_VkVendor = 20803,
215     };
216 
217     void init(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface,
218               VkPhysicalDevice device, const VkPhysicalDeviceFeatures2&,
219               uint32_t physicalDeviceVersion, const GrVkExtensions&, GrProtected isProtected);
220     void initGrCaps(const GrVkInterface* vkInterface,
221                     VkPhysicalDevice physDev,
222                     const VkPhysicalDeviceProperties&,
223                     const VkPhysicalDeviceMemoryProperties&,
224                     const VkPhysicalDeviceFeatures2&,
225                     const GrVkExtensions&);
226     void initShaderCaps(const VkPhysicalDeviceProperties&, const VkPhysicalDeviceFeatures2&);
227 
228     void initFormatTable(const GrVkInterface*, VkPhysicalDevice, const VkPhysicalDeviceProperties&);
229     void initStencilFormat(const GrVkInterface* iface, VkPhysicalDevice physDev);
230 
231     void applyDriverCorrectnessWorkarounds(const VkPhysicalDeviceProperties&);
232 
233     bool onSurfaceSupportsWritePixels(const GrSurface*) const override;
234     bool onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
235                           const SkIRect& srcRect, const SkIPoint& dstPoint) const override;
236     GrBackendFormat onGetDefaultBackendFormat(GrColorType) const override;
237 
238     bool onAreColorTypeAndFormatCompatible(GrColorType, const GrBackendFormat&) const override;
239 
240     SupportedRead onSupportedReadPixelsColorType(GrColorType, const GrBackendFormat&,
241                                                  GrColorType) const override;
242 
243     GrSwizzle onGetReadSwizzle(const GrBackendFormat&, GrColorType) const override;
244 
245     GrDstSampleType onGetDstSampleTypeForProxy(const GrRenderTargetProxy*) const override;
246 
247     // ColorTypeInfo for a specific format
248     struct ColorTypeInfo {
249         GrColorType fColorType = GrColorType::kUnknown;
250         enum {
251             kUploadData_Flag = 0x1,
252             // Does Ganesh itself support rendering to this colorType & format pair. Renderability
253             // still additionally depends on if the format itself is renderable.
254             kRenderable_Flag = 0x2,
255             // Indicates that this colorType is supported only if we are wrapping a texture with
256             // the given format and colorType. We do not allow creation with this pair.
257             kWrappedOnly_Flag = 0x4,
258         };
259         uint32_t fFlags = 0;
260 
261         GrSwizzle fReadSwizzle;
262         GrSwizzle fWriteSwizzle;
263     };
264 
265     struct FormatInfo {
colorTypeFlagsFormatInfo266         uint32_t colorTypeFlags(GrColorType colorType) const {
267             for (int i = 0; i < fColorTypeInfoCount; ++i) {
268                 if (fColorTypeInfos[i].fColorType == colorType) {
269                     return fColorTypeInfos[i].fFlags;
270                 }
271             }
272             return 0;
273         }
274 
275         void init(const GrVkInterface*, VkPhysicalDevice, const VkPhysicalDeviceProperties&,
276                   VkFormat);
277         static void InitFormatFlags(VkFormatFeatureFlags, uint16_t* flags);
278         void initSampleCounts(const GrVkInterface*, VkPhysicalDevice,
279                               const VkPhysicalDeviceProperties&, VkFormat);
280 
281         enum {
282             kTexturable_Flag = 0x1,
283             kRenderable_Flag = 0x2,
284             kBlitSrc_Flag    = 0x4,
285             kBlitDst_Flag    = 0x8,
286         };
287 
288         uint16_t fOptimalFlags = 0;
289         uint16_t fLinearFlags = 0;
290 
291         SkTDArray<int> fColorSampleCounts;
292 
293         std::unique_ptr<ColorTypeInfo[]> fColorTypeInfos;
294         int fColorTypeInfoCount = 0;
295     };
296     static const size_t kNumVkFormats = 22;
297     FormatInfo fFormatTable[kNumVkFormats];
298 
299     FormatInfo& getFormatInfo(VkFormat);
300     const FormatInfo& getFormatInfo(VkFormat) const;
301 
302     VkFormat fColorTypeToFormatTable[kGrColorTypeCnt];
303     void setColorType(GrColorType, std::initializer_list<VkFormat> formats);
304 
305     VkFormat fPreferredStencilFormat;
306 
307     SkSTArray<1, GrVkYcbcrConversionInfo> fYcbcrInfos;
308 
309     bool fMustSleepOnTearDown = false;
310     bool fShouldAlwaysUseDedicatedImageMemory = false;
311 
312     bool fAvoidUpdateBuffers = false;
313 
314     bool fSupportsSwapchain = false;
315 
316     bool fSupportsPhysicalDeviceProperties2 = false;
317     bool fSupportsMemoryRequirements2 = false;
318     bool fSupportsBindMemory2 = false;
319     bool fSupportsMaintenance1 = false;
320     bool fSupportsMaintenance2 = false;
321     bool fSupportsMaintenance3 = false;
322 
323     bool fSupportsDedicatedAllocation = false;
324     bool fSupportsExternalMemory = false;
325     bool fSupportsAndroidHWBExternalMemory = false;
326 
327     bool fSupportsYcbcrConversion = false;
328 
329     bool fSupportsProtectedMemory = false;
330 
331     bool fPreferPrimaryOverSecondaryCommandBuffers = true;
332     bool fMustInvalidatePrimaryCmdBufferStateAfterClearAttachments = false;
333 
334     // We default this to 100 since we already cap the max render tasks at 100 before doing a
335     // submission in the GrDrawingManager, so we shouldn't be going over 100 secondary command
336     // buffers per primary anyways.
337     int fMaxPerPoolCachedSecondaryCommandBuffers = 100;
338 
339     uint32_t fMaxInputAttachmentDescriptors = 0;
340 
341     bool fPreferCachedCpuMemory = true;
342 
343     using INHERITED = GrCaps;
344 };
345 
346 #endif
347