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 "GrCaps.h"
12 #include "GrVkStencilAttachment.h"
13 #include "vk/GrVkTypes.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     typedef GrVkStencilAttachment::Format StencilFormat;
25 
26     /**
27      * Creates a GrVkCaps that is set such that nothing is supported. The init function should
28      * be called to fill out the caps.
29      */
30     GrVkCaps(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface,
31              VkPhysicalDevice device, const VkPhysicalDeviceFeatures2& features,
32              uint32_t instanceVersion, uint32_t physicalDeviceVersion,
33              const GrVkExtensions& extensions);
34 
isConfigTexturable(GrPixelConfig config)35     bool isConfigTexturable(GrPixelConfig config) const override {
36         return SkToBool(ConfigInfo::kTextureable_Flag & fConfigTable[config].fOptimalFlags);
37     }
38 
isConfigCopyable(GrPixelConfig config)39     bool isConfigCopyable(GrPixelConfig config) const override {
40         return true;
41     }
42 
43     int getRenderTargetSampleCount(int requestedCount, GrPixelConfig config) const override;
44     int maxRenderTargetSampleCount(GrPixelConfig config) const override;
45 
46     bool surfaceSupportsReadPixels(const GrSurface*) const override;
47 
isConfigTexturableLinearly(GrPixelConfig config)48     bool isConfigTexturableLinearly(GrPixelConfig config) const {
49         return SkToBool(ConfigInfo::kTextureable_Flag & fConfigTable[config].fLinearFlags);
50     }
51 
isConfigRenderableLinearly(GrPixelConfig config,bool withMSAA)52     bool isConfigRenderableLinearly(GrPixelConfig config, bool withMSAA) const {
53         return !withMSAA && SkToBool(ConfigInfo::kRenderable_Flag &
54                                      fConfigTable[config].fLinearFlags);
55     }
56 
configCanBeDstofBlit(GrPixelConfig config,bool linearTiled)57     bool configCanBeDstofBlit(GrPixelConfig config, bool linearTiled) const {
58         const uint16_t& flags = linearTiled ? fConfigTable[config].fLinearFlags :
59                                               fConfigTable[config].fOptimalFlags;
60         return SkToBool(ConfigInfo::kBlitDst_Flag & flags);
61     }
62 
configCanBeSrcofBlit(GrPixelConfig config,bool linearTiled)63     bool configCanBeSrcofBlit(GrPixelConfig config, bool linearTiled) const {
64         const uint16_t& flags = linearTiled ? fConfigTable[config].fLinearFlags :
65                                               fConfigTable[config].fOptimalFlags;
66         return SkToBool(ConfigInfo::kBlitSrc_Flag & flags);
67     }
68 
69     // On Adreno vulkan, they do not respect the imageOffset parameter at least in
70     // copyImageToBuffer. This flag says that we must do the copy starting from the origin always.
mustDoCopiesFromOrigin()71     bool mustDoCopiesFromOrigin() const {
72         return fMustDoCopiesFromOrigin;
73     }
74 
75     // Sometimes calls to QueueWaitIdle return before actually signalling the fences
76     // on the command buffers even though they have completed. This causes an assert to fire when
77     // destroying the command buffers. Therefore we add a sleep to make sure the fence signals.
mustSleepOnTearDown()78     bool mustSleepOnTearDown() const {
79         return fMustSleepOnTearDown;
80     }
81 
82     // Returns true if while adding commands to command buffers, we must make a new command buffer
83     // everytime we want to bind a new VkPipeline. This is true for both primary and secondary
84     // command buffers. This is to work around a driver bug specifically on AMD.
newCBOnPipelineChange()85     bool newCBOnPipelineChange() const {
86         return fNewCBOnPipelineChange;
87     }
88 
89     // Returns true if we should always make dedicated allocations for VkImages.
shouldAlwaysUseDedicatedImageMemory()90     bool shouldAlwaysUseDedicatedImageMemory() const {
91         return fShouldAlwaysUseDedicatedImageMemory;
92     }
93 
94     // Always use a transfer buffer instead of vkCmdUpdateBuffer to upload data to a VkBuffer.
avoidUpdateBuffers()95     bool avoidUpdateBuffers() const {
96         return fAvoidUpdateBuffers;
97     }
98 
99     /**
100      * Returns both a supported and most preferred stencil format to use in draws.
101      */
preferredStencilFormat()102     const StencilFormat& preferredStencilFormat() const {
103         return fPreferredStencilFormat;
104     }
105 
106     // Returns whether the device supports VK_KHR_Swapchain. Internally Skia never uses any of the
107     // swapchain functions, but we may need to transition to and from the
108     // VK_IMAGE_LAYOUT_PRESENT_SRC_KHR image layout, so we must know whether that layout is
109     // supported.
supportsSwapchain()110     bool supportsSwapchain() const { return fSupportsSwapchain; }
111 
112     // Returns whether the device supports the ability to extend VkPhysicalDeviceProperties struct.
supportsPhysicalDeviceProperties2()113     bool supportsPhysicalDeviceProperties2() const { return fSupportsPhysicalDeviceProperties2; }
114     // Returns whether the device supports the ability to extend VkMemoryRequirements struct.
supportsMemoryRequirements2()115     bool supportsMemoryRequirements2() const { return fSupportsMemoryRequirements2; }
116 
117     // Returns whether the device supports the ability to extend the vkBindMemory call.
supportsBindMemory2()118     bool supportsBindMemory2() const { return fSupportsBindMemory2; }
119 
120     // Returns whether or not the device suports the various API maintenance fixes to Vulkan 1.0. In
121     // Vulkan 1.1 all these maintenance are part of the core spec.
supportsMaintenance1()122     bool supportsMaintenance1() const { return fSupportsMaintenance1; }
supportsMaintenance2()123     bool supportsMaintenance2() const { return fSupportsMaintenance2; }
supportsMaintenance3()124     bool supportsMaintenance3() const { return fSupportsMaintenance3; }
125 
126     // Returns true if the device supports passing in a flag to say we are using dedicated GPU when
127     // allocating memory. For some devices this allows them to return more optimized memory knowning
128     // they will never need to suballocate amonst multiple objects.
supportsDedicatedAllocation()129     bool supportsDedicatedAllocation() const { return fSupportsDedicatedAllocation; }
130 
131     // Returns true if the device supports importing of external memory into Vulkan memory.
supportsExternalMemory()132     bool supportsExternalMemory() const { return fSupportsExternalMemory; }
133     // Returns true if the device supports importing Android hardware buffers into Vulkan memory.
supportsAndroidHWBExternalMemory()134     bool supportsAndroidHWBExternalMemory() const { return fSupportsAndroidHWBExternalMemory; }
135 
136     // Returns true if it supports ycbcr conversion for samplers
supportsYcbcrConversion()137     bool supportsYcbcrConversion() const { return fSupportsYcbcrConversion; }
138 
139     /**
140      * Helpers used by canCopySurface. In all cases if the SampleCnt parameter is zero that means
141      * the surface is not a render target, otherwise it is the number of samples in the render
142      * target.
143      */
144     bool canCopyImage(GrPixelConfig dstConfig, int dstSampleCnt, GrSurfaceOrigin dstOrigin,
145                       bool dstHasYcbcr, GrPixelConfig srcConfig, int srcSamplecnt,
146                       GrSurfaceOrigin srcOrigin, bool srcHasYcbcr) const;
147 
148     bool canCopyAsBlit(GrPixelConfig dstConfig, int dstSampleCnt, bool dstIsLinear,
149                        bool dstHasYcbcr, GrPixelConfig srcConfig, int srcSampleCnt,
150                        bool srcIsLinear, bool srcHasYcbcr) const;
151 
152     bool canCopyAsResolve(GrPixelConfig dstConfig, int dstSampleCnt, GrSurfaceOrigin dstOrigin,
153                           bool dstHasYcbcr, GrPixelConfig srcConfig, int srcSamplecnt,
154                           GrSurfaceOrigin srcOrigin, bool srcHasYcbcr) const;
155 
156     bool canCopyAsDraw(GrPixelConfig dstConfig, bool dstIsRenderable, bool dstHasYcbcr,
157                        GrPixelConfig srcConfig, bool srcIsTextureable, bool srcHasYcbcr) const;
158 
159     bool initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc, GrSurfaceOrigin*,
160                             bool* rectsMustMatch, bool* disallowSubrect) const override;
161 
162     GrPixelConfig validateBackendRenderTarget(const GrBackendRenderTarget&,
163                                               SkColorType) const override;
164 
165     GrPixelConfig getConfigFromBackendFormat(const GrBackendFormat&, SkColorType) const override;
166     GrPixelConfig getYUVAConfigFromBackendFormat(const GrBackendFormat&) const override;
167 
168     GrBackendFormat getBackendFormatFromGrColorType(GrColorType ct,
169                                                     GrSRGBEncoded srgbEncoded) const override;
170 
171 private:
172     enum VkVendor {
173         kAMD_VkVendor = 4098,
174         kARM_VkVendor = 5045,
175         kImagination_VkVendor = 4112,
176         kIntel_VkVendor = 32902,
177         kNvidia_VkVendor = 4318,
178         kQualcomm_VkVendor = 20803,
179     };
180 
181     void init(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface,
182               VkPhysicalDevice device, const VkPhysicalDeviceFeatures2&,
183               uint32_t physicalDeviceVersion, const GrVkExtensions&);
184     void initGrCaps(const GrVkInterface* vkInterface,
185                     VkPhysicalDevice physDev,
186                     const VkPhysicalDeviceProperties&,
187                     const VkPhysicalDeviceMemoryProperties&,
188                     const VkPhysicalDeviceFeatures2&,
189                     const GrVkExtensions&);
190     void initShaderCaps(const VkPhysicalDeviceProperties&, const VkPhysicalDeviceFeatures2&);
191 
192     void initConfigTable(const GrVkInterface*, VkPhysicalDevice, const VkPhysicalDeviceProperties&);
193     void initStencilFormat(const GrVkInterface* iface, VkPhysicalDevice physDev);
194 
195     uint8_t getYcbcrKeyFromYcbcrInfo(const GrVkYcbcrConversionInfo& info);
196 
197     void applyDriverCorrectnessWorkarounds(const VkPhysicalDeviceProperties&);
198 
199     bool onSurfaceSupportsWritePixels(const GrSurface*) const override;
200     bool onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
201                           const SkIRect& srcRect, const SkIPoint& dstPoint) const override;
202 
203     struct ConfigInfo {
ConfigInfoConfigInfo204         ConfigInfo() : fOptimalFlags(0), fLinearFlags(0) {}
205 
206         void init(const GrVkInterface*, VkPhysicalDevice, const VkPhysicalDeviceProperties&,
207                   VkFormat, bool disableRendering);
208         static void InitConfigFlags(VkFormatFeatureFlags, uint16_t* flags, bool disableRendering);
209         void initSampleCounts(const GrVkInterface*, VkPhysicalDevice,
210                               const VkPhysicalDeviceProperties&, VkFormat);
211 
212         enum {
213             kTextureable_Flag = 0x1,
214             kRenderable_Flag  = 0x2,
215             kBlitSrc_Flag     = 0x4,
216             kBlitDst_Flag     = 0x8,
217         };
218 
219         uint16_t fOptimalFlags;
220         uint16_t fLinearFlags;
221 
222         SkTDArray<int> fColorSampleCounts;
223     };
224     ConfigInfo fConfigTable[kGrPixelConfigCnt];
225 
226     StencilFormat fPreferredStencilFormat;
227 
228     SkSTArray<1, GrVkYcbcrConversionInfo> fYcbcrInfos;
229 
230     bool fMustDoCopiesFromOrigin = false;
231     bool fMustSleepOnTearDown = false;
232     bool fNewCBOnPipelineChange = false;
233     bool fShouldAlwaysUseDedicatedImageMemory = false;
234 
235     bool fAvoidUpdateBuffers = false;
236 
237     bool fSupportsSwapchain = false;
238 
239     bool fSupportsPhysicalDeviceProperties2 = false;
240     bool fSupportsMemoryRequirements2 = false;
241     bool fSupportsBindMemory2 = false;
242     bool fSupportsMaintenance1 = false;
243     bool fSupportsMaintenance2 = false;
244     bool fSupportsMaintenance3 = false;
245 
246     bool fSupportsDedicatedAllocation = false;
247     bool fSupportsExternalMemory = false;
248     bool fSupportsAndroidHWBExternalMemory = false;
249 
250     bool fSupportsYcbcrConversion = false;
251 
252     typedef GrCaps INHERITED;
253 };
254 
255 #endif
256