• 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 #include "src/gpu/vk/GrVkCaps.h"
9 
10 #include <memory>
11 
12 #include "include/gpu/GrBackendSurface.h"
13 #include "include/gpu/vk/GrVkBackendContext.h"
14 #include "include/gpu/vk/GrVkExtensions.h"
15 #include "src/core/SkCompressedDataUtils.h"
16 #include "src/gpu/GrBackendUtils.h"
17 #include "src/gpu/GrProgramDesc.h"
18 #include "src/gpu/GrRenderTarget.h"
19 #include "src/gpu/GrRenderTargetProxy.h"
20 #include "src/gpu/GrShaderCaps.h"
21 #include "src/gpu/GrStencilSettings.h"
22 #include "src/gpu/GrUtil.h"
23 #include "src/gpu/SkGr.h"
24 #include "src/gpu/vk/GrVkGpu.h"
25 #include "src/gpu/vk/GrVkImage.h"
26 #include "src/gpu/vk/GrVkInterface.h"
27 #include "src/gpu/vk/GrVkRenderTarget.h"
28 #include "src/gpu/vk/GrVkTexture.h"
29 #include "src/gpu/vk/GrVkUniformHandler.h"
30 #include "src/gpu/vk/GrVkUtil.h"
31 #ifdef SUPPORT_OPAQUE_OPTIMIZATION
32 #include <parameters.h>
33 #endif
34 
35 #ifdef SK_BUILD_FOR_ANDROID
36 #include <sys/system_properties.h>
37 #endif
38 
39 #ifdef SUPPORT_OPAQUE_OPTIMIZATION
40 #define SK_OPAQUE_REGION_HARDWARE_SUPPORT_MIN_VERSION 0x20021000
41 #endif
42 
GrVkCaps(const GrContextOptions & contextOptions,const GrVkInterface * vkInterface,VkPhysicalDevice physDev,const VkPhysicalDeviceFeatures2 & features,uint32_t instanceVersion,uint32_t physicalDeviceVersion,const GrVkExtensions & extensions,GrProtected isProtected)43 GrVkCaps::GrVkCaps(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface,
44                    VkPhysicalDevice physDev, const VkPhysicalDeviceFeatures2& features,
45                    uint32_t instanceVersion, uint32_t physicalDeviceVersion,
46                    const GrVkExtensions& extensions, GrProtected isProtected)
47         : INHERITED(contextOptions) {
48     /**************************************************************************
49      * GrCaps fields
50      **************************************************************************/
51     fMipmapSupport = true;   // always available in Vulkan
52     fNPOTTextureTileSupport = true;  // always available in Vulkan
53     fReuseScratchTextures = true; //TODO: figure this out
54     fGpuTracingSupport = false; //TODO: figure this out
55     fOversizedStencilSupport = false; //TODO: figure this out
56     fDrawInstancedSupport = true;
57 
58     fSemaphoreSupport = true;   // always available in Vulkan
59     fFenceSyncSupport = true;   // always available in Vulkan
60     fCrossContextTextureSupport = true;
61     fHalfFloatVertexAttributeSupport = true;
62 
63     // We always copy in/out of a transfer buffer so it's trivial to support row bytes.
64     fReadPixelsRowBytesSupport = true;
65     fWritePixelsRowBytesSupport = true;
66 
67     fTransferFromBufferToTextureSupport = true;
68     fTransferFromSurfaceToBufferSupport = true;
69 
70     fMaxRenderTargetSize = 4096; // minimum required by spec
71     fMaxTextureSize = 4096; // minimum required by spec
72 
73     fDynamicStateArrayGeometryProcessorTextureSupport = true;
74 
75     fTextureBarrierSupport = true;
76 
77     fShaderCaps = std::make_unique<GrShaderCaps>();
78 
79     this->init(contextOptions, vkInterface, physDev, features, physicalDeviceVersion, extensions,
80                isProtected);
81 }
82 
83 namespace {
84 /**
85  * This comes from section 37.1.6 of the Vulkan spec. Format is
86  * (<bits>|<tag>)_<block_size>_<texels_per_block>.
87  */
88 enum class FormatCompatibilityClass {
89     k8_1_1,
90     k16_2_1,
91     k24_3_1,
92     k32_4_1,
93     k64_8_1,
94     kBC1_RGB_8_16_1,
95     kBC1_RGBA_8_16,
96     kETC2_RGB_8_16,
97     kASTC_RGBA_8_16,
98 };
99 }  // anonymous namespace
100 
format_compatibility_class(VkFormat format)101 static FormatCompatibilityClass format_compatibility_class(VkFormat format) {
102     switch (format) {
103         case VK_FORMAT_B8G8R8A8_UNORM:
104         case VK_FORMAT_R8G8B8A8_UNORM:
105         case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
106         case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
107         case VK_FORMAT_R8G8B8A8_SRGB:
108         case VK_FORMAT_R16G16_UNORM:
109         case VK_FORMAT_R16G16_SFLOAT:
110             return FormatCompatibilityClass::k32_4_1;
111 
112         case VK_FORMAT_R8_UNORM:
113             return FormatCompatibilityClass::k8_1_1;
114 
115         case VK_FORMAT_R5G6B5_UNORM_PACK16:
116         case VK_FORMAT_R16_SFLOAT:
117         case VK_FORMAT_R8G8_UNORM:
118         case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
119         case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
120         case VK_FORMAT_R16_UNORM:
121             return FormatCompatibilityClass::k16_2_1;
122 
123         case VK_FORMAT_R16G16B16A16_SFLOAT:
124         case VK_FORMAT_R16G16B16A16_UNORM:
125             return FormatCompatibilityClass::k64_8_1;
126 
127         case VK_FORMAT_R8G8B8_UNORM:
128             return FormatCompatibilityClass::k24_3_1;
129 
130         case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
131             return FormatCompatibilityClass::kETC2_RGB_8_16;
132 
133         case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
134             return FormatCompatibilityClass::kBC1_RGB_8_16_1;
135 
136         case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
137             return FormatCompatibilityClass::kBC1_RGBA_8_16;
138 
139         case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:
140         case VK_FORMAT_ASTC_6x6_UNORM_BLOCK:
141         case VK_FORMAT_ASTC_8x8_UNORM_BLOCK:
142             return FormatCompatibilityClass::kASTC_RGBA_8_16;
143 
144         default:
145             SK_ABORT("Unsupported VkFormat");
146     }
147 }
148 
canCopyImage(VkFormat dstFormat,int dstSampleCnt,bool dstHasYcbcr,VkFormat srcFormat,int srcSampleCnt,bool srcHasYcbcr) const149 bool GrVkCaps::canCopyImage(VkFormat dstFormat, int dstSampleCnt, bool dstHasYcbcr,
150                             VkFormat srcFormat, int srcSampleCnt, bool srcHasYcbcr) const {
151     if ((dstSampleCnt > 1 || srcSampleCnt > 1) && dstSampleCnt != srcSampleCnt) {
152         return false;
153     }
154 
155     if (dstHasYcbcr || srcHasYcbcr) {
156         return false;
157     }
158 
159     // We require that all Vulkan GrSurfaces have been created with transfer_dst and transfer_src
160     // as image usage flags.
161     return format_compatibility_class(srcFormat) == format_compatibility_class(dstFormat);
162 }
163 
canCopyAsBlit(VkFormat dstFormat,int dstSampleCnt,bool dstIsLinear,bool dstHasYcbcr,VkFormat srcFormat,int srcSampleCnt,bool srcIsLinear,bool srcHasYcbcr) const164 bool GrVkCaps::canCopyAsBlit(VkFormat dstFormat, int dstSampleCnt, bool dstIsLinear,
165                              bool dstHasYcbcr, VkFormat srcFormat, int srcSampleCnt,
166                              bool srcIsLinear, bool srcHasYcbcr) const {
167     // We require that all vulkan GrSurfaces have been created with transfer_dst and transfer_src
168     // as image usage flags.
169     if (!this->formatCanBeDstofBlit(dstFormat, dstIsLinear) ||
170         !this->formatCanBeSrcofBlit(srcFormat, srcIsLinear)) {
171         return false;
172     }
173 
174     // We cannot blit images that are multisampled. Will need to figure out if we can blit the
175     // resolved msaa though.
176     if (dstSampleCnt > 1 || srcSampleCnt > 1) {
177         return false;
178     }
179 
180     if (dstHasYcbcr || srcHasYcbcr) {
181         return false;
182     }
183 
184     return true;
185 }
186 
canCopyAsResolve(VkFormat dstFormat,int dstSampleCnt,bool dstHasYcbcr,VkFormat srcFormat,int srcSampleCnt,bool srcHasYcbcr) const187 bool GrVkCaps::canCopyAsResolve(VkFormat dstFormat, int dstSampleCnt, bool dstHasYcbcr,
188                                 VkFormat srcFormat, int srcSampleCnt, bool srcHasYcbcr) const {
189     // The src surface must be multisampled.
190     if (srcSampleCnt <= 1) {
191         return false;
192     }
193 
194     // The dst must not be multisampled.
195     if (dstSampleCnt > 1) {
196         return false;
197     }
198 
199     // Surfaces must have the same format.
200     if (srcFormat != dstFormat) {
201         return false;
202     }
203 
204     if (dstHasYcbcr || srcHasYcbcr) {
205         return false;
206     }
207 
208     return true;
209 }
210 
onCanCopySurface(const GrSurfaceProxy * dst,const GrSurfaceProxy * src,const SkIRect & srcRect,const SkIPoint & dstPoint) const211 bool GrVkCaps::onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
212                                 const SkIRect& srcRect, const SkIPoint& dstPoint) const {
213     if (src->isProtected() == GrProtected::kYes && dst->isProtected() != GrProtected::kYes) {
214         return false;
215     }
216 
217     // TODO: Figure out a way to track if we've wrapped a linear texture in a proxy (e.g.
218     // PromiseImage which won't get instantiated right away. Does this need a similar thing like the
219     // tracking of external or rectangle textures in GL? For now we don't create linear textures
220     // internally, and I don't believe anyone is wrapping them.
221     bool srcIsLinear = false;
222     bool dstIsLinear = false;
223 
224     int dstSampleCnt = 0;
225     int srcSampleCnt = 0;
226     if (const GrRenderTargetProxy* rtProxy = dst->asRenderTargetProxy()) {
227         // Copying to or from render targets that wrap a secondary command buffer is not allowed
228         // since they would require us to know the VkImage, which we don't have, as well as need us
229         // to stop and start the VkRenderPass which we don't have access to.
230         if (rtProxy->wrapsVkSecondaryCB()) {
231             return false;
232         }
233         if (this->preferDiscardableMSAAAttachment() && dst->asTextureProxy() &&
234             rtProxy->supportsVkInputAttachment()) {
235             dstSampleCnt = 1;
236         } else {
237             dstSampleCnt = rtProxy->numSamples();
238         }
239     }
240     if (const GrRenderTargetProxy* rtProxy = src->asRenderTargetProxy()) {
241         // Copying to or from render targets that wrap a secondary command buffer is not allowed
242         // since they would require us to know the VkImage, which we don't have, as well as need us
243         // to stop and start the VkRenderPass which we don't have access to.
244         if (rtProxy->wrapsVkSecondaryCB()) {
245             return false;
246         }
247         if (this->preferDiscardableMSAAAttachment() && src->asTextureProxy() &&
248             rtProxy->supportsVkInputAttachment()) {
249             srcSampleCnt = 1;
250         } else {
251             srcSampleCnt = rtProxy->numSamples();
252         }
253     }
254     SkASSERT((dstSampleCnt > 0) == SkToBool(dst->asRenderTargetProxy()));
255     SkASSERT((srcSampleCnt > 0) == SkToBool(src->asRenderTargetProxy()));
256 
257     bool dstHasYcbcr = false;
258     if (auto ycbcr = dst->backendFormat().getVkYcbcrConversionInfo()) {
259         if (ycbcr->isValid()) {
260             dstHasYcbcr = true;
261         }
262     }
263 
264     bool srcHasYcbcr = false;
265     if (auto ycbcr = src->backendFormat().getVkYcbcrConversionInfo()) {
266         if (ycbcr->isValid()) {
267             srcHasYcbcr = true;
268         }
269     }
270 
271     VkFormat dstFormat, srcFormat;
272     SkAssertResult(dst->backendFormat().asVkFormat(&dstFormat));
273     SkAssertResult(src->backendFormat().asVkFormat(&srcFormat));
274 
275     return this->canCopyImage(dstFormat, dstSampleCnt, dstHasYcbcr,
276                               srcFormat, srcSampleCnt, srcHasYcbcr) ||
277            this->canCopyAsBlit(dstFormat, dstSampleCnt, dstIsLinear, dstHasYcbcr,
278                                srcFormat, srcSampleCnt, srcIsLinear, srcHasYcbcr) ||
279            this->canCopyAsResolve(dstFormat, dstSampleCnt, dstHasYcbcr,
280                                   srcFormat, srcSampleCnt, srcHasYcbcr);
281 }
282 
get_extension_feature_struct(const VkPhysicalDeviceFeatures2 & features,VkStructureType type)283 template<typename T> T* get_extension_feature_struct(const VkPhysicalDeviceFeatures2& features,
284                                                      VkStructureType type) {
285     // All Vulkan structs that could be part of the features chain will start with the
286     // structure type followed by the pNext pointer. We cast to the CommonVulkanHeader
287     // so we can get access to the pNext for the next struct.
288     struct CommonVulkanHeader {
289         VkStructureType sType;
290         void*           pNext;
291     };
292 
293     void* pNext = features.pNext;
294     while (pNext) {
295         CommonVulkanHeader* header = static_cast<CommonVulkanHeader*>(pNext);
296         if (header->sType == type) {
297             return static_cast<T*>(pNext);
298         }
299         pNext = header->pNext;
300     }
301     return nullptr;
302 }
303 
init(const GrContextOptions & contextOptions,const GrVkInterface * vkInterface,VkPhysicalDevice physDev,const VkPhysicalDeviceFeatures2 & features,uint32_t physicalDeviceVersion,const GrVkExtensions & extensions,GrProtected isProtected)304 void GrVkCaps::init(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface,
305                     VkPhysicalDevice physDev, const VkPhysicalDeviceFeatures2& features,
306                     uint32_t physicalDeviceVersion, const GrVkExtensions& extensions,
307                     GrProtected isProtected) {
308     VkPhysicalDeviceProperties properties;
309     GR_VK_CALL(vkInterface, GetPhysicalDeviceProperties(physDev, &properties));
310 
311     VkPhysicalDeviceMemoryProperties memoryProperties;
312     GR_VK_CALL(vkInterface, GetPhysicalDeviceMemoryProperties(physDev, &memoryProperties));
313 
314     SkASSERT(physicalDeviceVersion <= properties.apiVersion);
315 
316     if (extensions.hasExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME, 1)) {
317         fSupportsSwapchain = true;
318     }
319 
320     if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
321         extensions.hasExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 1)) {
322         fSupportsPhysicalDeviceProperties2 = true;
323     }
324 
325     if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
326         extensions.hasExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, 1)) {
327         fSupportsMemoryRequirements2 = true;
328     }
329 
330     if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
331         extensions.hasExtension(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME, 1)) {
332         fSupportsBindMemory2 = true;
333     }
334 
335     if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
336         extensions.hasExtension(VK_KHR_MAINTENANCE1_EXTENSION_NAME, 1)) {
337         fSupportsMaintenance1 = true;
338     }
339 
340     if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
341         extensions.hasExtension(VK_KHR_MAINTENANCE2_EXTENSION_NAME, 1)) {
342         fSupportsMaintenance2 = true;
343     }
344 
345     if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
346         extensions.hasExtension(VK_KHR_MAINTENANCE3_EXTENSION_NAME, 1)) {
347         fSupportsMaintenance3 = true;
348     }
349 
350     if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
351         (extensions.hasExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, 1) &&
352          this->supportsMemoryRequirements2())) {
353         fSupportsDedicatedAllocation = true;
354     }
355 
356     if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
357         (extensions.hasExtension(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, 1) &&
358          this->supportsPhysicalDeviceProperties2() &&
359          extensions.hasExtension(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME, 1) &&
360          this->supportsDedicatedAllocation())) {
361         fSupportsExternalMemory = true;
362     }
363 
364 #ifdef SK_BUILD_FOR_ANDROID
365     // Currently Adreno devices are not supporting the QUEUE_FAMILY_FOREIGN_EXTENSION, so until they
366     // do we don't explicitly require it here even the spec says it is required.
367     if (extensions.hasExtension(
368             VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME, 2) &&
369        /* extensions.hasExtension(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME, 1) &&*/
370         this->supportsExternalMemory() &&
371         this->supportsBindMemory2()) {
372         fSupportsAndroidHWBExternalMemory = true;
373         fSupportsAHardwareBufferImages = true;
374     }
375 #endif
376 
377     auto ycbcrFeatures =
378             get_extension_feature_struct<VkPhysicalDeviceSamplerYcbcrConversionFeatures>(
379                     features, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES);
380     if (ycbcrFeatures && ycbcrFeatures->samplerYcbcrConversion &&
381         (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
382          (extensions.hasExtension(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, 1) &&
383           this->supportsMaintenance1() && this->supportsBindMemory2() &&
384           this->supportsMemoryRequirements2() && this->supportsPhysicalDeviceProperties2()))) {
385         fSupportsYcbcrConversion = true;
386     }
387 
388     // We always push back the default GrVkYcbcrConversionInfo so that the case of no conversion
389     // will return a key of 0.
390     fYcbcrInfos.push_back(GrVkYcbcrConversionInfo());
391 
392     if ((isProtected == GrProtected::kYes) &&
393         (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0))) {
394         fSupportsProtectedMemory = true;
395         fAvoidUpdateBuffers = true;
396         fShouldAlwaysUseDedicatedImageMemory = true;
397     }
398 
399     if (extensions.hasExtension(VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME, 1)) {
400         fSupportsDRMFormatModifiers = true;
401     }
402 
403     fMaxInputAttachmentDescriptors = properties.limits.maxDescriptorSetInputAttachments;
404 
405     // On desktop GPUs we have found that this does not provide much benefit. The perf results show
406     // a mix of regressions, some improvements, and lots of no changes. Thus it is no worth enabling
407     // this (especially with the rendering artifacts) on desktop.
408     //
409     // On Adreno devices we were expecting to see perf gains. But instead there were actually a lot
410     // of perf regressions and only a few perf wins. This needs some follow up with qualcomm since
411     // we do expect this to be a big win on tilers.
412     //
413     // On ARM devices we are seeing an average perf win of around 50%-60% across the board.
414     if (kARM_VkVendor == properties.vendorID || kHisi_VkVendor == properties.vendorID) {
415         fPreferDiscardableMSAAAttachment = true;
416         fSupportsMemorylessAttachments = true;
417     }
418 
419     this->initGrCaps(vkInterface, physDev, properties, memoryProperties, features, extensions);
420     this->initShaderCaps(properties, features);
421 
422     if (kQualcomm_VkVendor == properties.vendorID) {
423         // A "clear" load for atlases runs faster on QC than a "discard" load followed by a
424         // scissored clear.
425         // On NVIDIA and Intel, the discard load followed by clear is faster.
426         // TODO: Evaluate on ARM, Imagination, and ATI.
427         fPreferFullscreenClears = true;
428     }
429 
430     if (properties.vendorID == kNvidia_VkVendor || properties.vendorID == kAMD_VkVendor) {
431         // On discrete GPUs it can be faster to read gpu only memory compared to memory that is also
432         // mappable on the host.
433         fGpuOnlyBuffersMorePerformant = true;
434 
435         // On discrete GPUs we try to use special DEVICE_LOCAL and HOST_VISIBLE memory for our
436         // cpu write, gpu read buffers. This memory is not ideal to be kept persistently mapped.
437         // Some discrete GPUs do not expose this special memory, however we still disable
438         // persistently mapped buffers for all of them since most GPUs with updated drivers do
439         // expose it. If this becomes an issue we can try to be more fine grained.
440         fShouldPersistentlyMapCpuToGpuBuffers = false;
441     }
442 
443     if (kQualcomm_VkVendor == properties.vendorID) {
444         // On Qualcomm it looks like using vkCmdUpdateBuffer is slower than using a transfer buffer
445         // even for small sizes.
446         fAvoidUpdateBuffers = true;
447     }
448 
449     if (kQualcomm_VkVendor == properties.vendorID) {
450         // Adreno devices don't support push constants well
451         fMaxPushConstantsSize = 0;
452     }
453 
454     fNativeDrawIndirectSupport = features.features.drawIndirectFirstInstance;
455     if (properties.vendorID == kQualcomm_VkVendor) {
456         // Indirect draws seem slow on QC. Disable until we can investigate. http://skbug.com/11139
457         fNativeDrawIndirectSupport = false;
458     }
459 
460     if (fNativeDrawIndirectSupport) {
461         fMaxDrawIndirectDrawCount = properties.limits.maxDrawIndirectCount;
462         SkASSERT(fMaxDrawIndirectDrawCount == 1 || features.features.multiDrawIndirect);
463     }
464 
465 #ifdef SK_BUILD_FOR_UNIX
466     if (kNvidia_VkVendor == properties.vendorID) {
467         // On nvidia linux we see a big perf regression when not using dedicated image allocations.
468         fShouldAlwaysUseDedicatedImageMemory = true;
469     }
470 #endif
471 
472     this->initFormatTable(vkInterface, physDev, properties);
473     this->initStencilFormat(vkInterface, physDev);
474 
475     if (contextOptions.fMaxCachedVulkanSecondaryCommandBuffers >= 0) {
476         fMaxPerPoolCachedSecondaryCommandBuffers =
477                 contextOptions.fMaxCachedVulkanSecondaryCommandBuffers;
478     }
479 
480     if (!contextOptions.fDisableDriverCorrectnessWorkarounds) {
481         this->applyDriverCorrectnessWorkarounds(properties);
482     }
483 
484     this->finishInitialization(contextOptions);
485 }
486 
applyDriverCorrectnessWorkarounds(const VkPhysicalDeviceProperties & properties)487 void GrVkCaps::applyDriverCorrectnessWorkarounds(const VkPhysicalDeviceProperties& properties) {
488 #if defined(SK_BUILD_FOR_WIN)
489     if (kNvidia_VkVendor == properties.vendorID || kIntel_VkVendor == properties.vendorID) {
490         fMustSyncCommandBuffersWithQueue = true;
491     }
492 #elif defined(SK_BUILD_FOR_ANDROID)
493     if (kImagination_VkVendor == properties.vendorID) {
494         fMustSyncCommandBuffersWithQueue = true;
495     }
496 #endif
497 
498     // Defaults to zero since all our workaround checks that use this consider things "fixed" once
499     // above a certain api level. So this will just default to it being less which will enable
500     // workarounds.
501     int androidAPIVersion = 0;
502 #if defined(SK_BUILD_FOR_ANDROID)
503     char androidAPIVersionStr[PROP_VALUE_MAX];
504     int strLength = __system_property_get("ro.build.version.sdk", androidAPIVersionStr);
505     // Defaults to zero since most checks care if it is greater than a specific value. So this will
506     // just default to it being less.
507     androidAPIVersion = (strLength == 0) ? 0 : atoi(androidAPIVersionStr);
508 #endif
509 
510     // Protected memory features have problems in Android P and earlier.
511     if (fSupportsProtectedMemory && (kQualcomm_VkVendor == properties.vendorID)) {
512         if (androidAPIVersion <= 28) {
513             fSupportsProtectedMemory = false;
514         }
515     }
516 
517     // On Mali galaxy s7 we see lots of rendering issues when we suballocate VkImages.
518     if ((kARM_VkVendor == properties.vendorID || kHisi_VkVendor == properties.vendorID) && androidAPIVersion <= 28) {
519         fShouldAlwaysUseDedicatedImageMemory = true;
520     }
521 
522 #if defined(SK_BUILD_FOR_OLD_MALI)
523     // On Mali galaxy s7 and s9 we see lots of rendering issues with image filters dropping out when
524     // using only primary command buffers. We also see issues on the P30 running android 28.
525     if ((kARM_VkVendor == properties.vendorID) && androidAPIVersion <= 28) {
526         fPreferPrimaryOverSecondaryCommandBuffers = false;
527         // If we are using secondary command buffers our code isn't setup to insert barriers into
528         // the secondary cb so we need to disable support for them.
529         fTextureBarrierSupport = false;
530         fBlendEquationSupport = kBasic_BlendEquationSupport;
531     }
532 #endif
533 
534     // We've seen numerous driver bugs on qualcomm devices running on android P (api 28) or earlier
535     // when trying to using discardable msaa attachments and loading from resolve. So we disable the
536     // feature for those devices.
537     if (properties.vendorID == kQualcomm_VkVendor && androidAPIVersion <= 28) {
538         fPreferDiscardableMSAAAttachment = false;
539         fSupportsDiscardableMSAAForDMSAA = false;
540     }
541 
542     // On Mali G series GPUs, applying transfer functions in the fragment shader with half-floats
543     // produces answers that are much less accurate than expected/required. This forces full floats
544     // for some intermediate values to get acceptable results.
545     if (kARM_VkVendor == properties.vendorID || kHisi_VkVendor == properties.vendorID) {
546         fShaderCaps->fColorSpaceMathNeedsFloat = true;
547     }
548 
549     // On various devices, when calling vkCmdClearAttachments on a primary command buffer, it
550     // corrupts the bound buffers on the command buffer. As a workaround we invalidate our knowledge
551     // of bound buffers so that we will rebind them on the next draw.
552     if (kQualcomm_VkVendor == properties.vendorID || kAMD_VkVendor == properties.vendorID) {
553         fMustInvalidatePrimaryCmdBufferStateAfterClearAttachments = true;
554     }
555 
556     // On Qualcomm and Arm the gpu resolves an area larger than the render pass bounds when using
557     // discardable msaa attachments. This causes the resolve to resolve uninitialized data from the
558     // msaa image into the resolve image.
559     if (kQualcomm_VkVendor == properties.vendorID || kARM_VkVendor == properties.vendorID
560         || kHisi_VkVendor == properties.vendorID) {
561         fMustLoadFullImageWithDiscardableMSAA = true;
562     }
563 
564 #ifdef SK_BUILD_FOR_UNIX
565     if (kIntel_VkVendor == properties.vendorID) {
566         // At least on our linux Debug Intel HD405 bot we are seeing issues doing read pixels with
567         // non-conherent memory. It seems like the device is not properly honoring the
568         // vkInvalidateMappedMemoryRanges calls correctly. Other linux intel devices seem to work
569         // okay. However, since I'm not sure how to target a specific intel devices or driver
570         // version I am going to stop all intel linux from using non-coherent memory. Currently we
571         // are not shipping anything on these platforms and the only real thing that will regress is
572         // read backs. If we find later we do care about this performance we can come back to figure
573         // out how to do a more narrow workaround.
574         fMustUseCoherentHostVisibleMemory = true;
575     }
576 #endif
577 
578     ////////////////////////////////////////////////////////////////////////////
579     // GrCaps workarounds
580     ////////////////////////////////////////////////////////////////////////////
581 
582 #ifdef SK_BUILD_FOR_ANDROID
583     // MSAA CCPR was slow on Android. http://skbug.com/9676
584     fDriverDisableMSAAClipAtlas = true;
585 #endif
586 
587     if (kARM_VkVendor == properties.vendorID) {
588         fAvoidWritePixelsFastPath = true; // bugs.skia.org/8064
589     }
590 
591     if (kHisi_VkVendor == properties.vendorID) {
592         fAvoidWritePixelsFastPath = false; // bugs.skia.org/8064
593     }
594 
595     // AMD advertises support for MAX_UINT vertex input attributes, but in reality only supports 32.
596     if (kAMD_VkVendor == properties.vendorID) {
597         fMaxVertexAttributes = std::min(fMaxVertexAttributes, 32);
598     }
599 
600     // Adreno devices fail when trying to read the dest using an input attachment and texture
601     // barriers.
602     if (kQualcomm_VkVendor == properties.vendorID) {
603         fTextureBarrierSupport = false;
604     }
605 
606     // On ARM indirect draws are broken on Android 9 and earlier. This was tested on a P30 and
607     // Mate 20x running android 9.
608     if ((properties.vendorID == kARM_VkVendor || kHisi_VkVendor == properties.vendorID) && androidAPIVersion <= 28) {
609         fNativeDrawIndirectSupport = false;
610     }
611 
612     ////////////////////////////////////////////////////////////////////////////
613     // GrShaderCaps workarounds
614     ////////////////////////////////////////////////////////////////////////////
615 
616     if (kImagination_VkVendor == properties.vendorID) {
617         fShaderCaps->fAtan2ImplementedAsAtanYOverX = true;
618     }
619 }
620 
initGrCaps(const GrVkInterface * vkInterface,VkPhysicalDevice physDev,const VkPhysicalDeviceProperties & properties,const VkPhysicalDeviceMemoryProperties & memoryProperties,const VkPhysicalDeviceFeatures2 & features,const GrVkExtensions & extensions)621 void GrVkCaps::initGrCaps(const GrVkInterface* vkInterface,
622                           VkPhysicalDevice physDev,
623                           const VkPhysicalDeviceProperties& properties,
624                           const VkPhysicalDeviceMemoryProperties& memoryProperties,
625                           const VkPhysicalDeviceFeatures2& features,
626                           const GrVkExtensions& extensions) {
627     // So GPUs, like AMD, are reporting MAX_INT support vertex attributes. In general, there is no
628     // need for us ever to support that amount, and it makes tests which tests all the vertex
629     // attribs timeout looping over that many. For now, we'll cap this at 64 max and can raise it if
630     // we ever find that need.
631     static const uint32_t kMaxVertexAttributes = 64;
632     fMaxVertexAttributes = std::min(properties.limits.maxVertexInputAttributes, kMaxVertexAttributes);
633 
634     // GrCaps::fSampleLocationsSupport refers to the ability to *query* the sample locations (not
635     // program them). For now we just set this to true if the device uses standard locations, and
636     // return the standard locations back when queried.
637     if (properties.limits.standardSampleLocations) {
638         fSampleLocationsSupport = true;
639     }
640 
641     if (extensions.hasExtension(VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME, 1)) {
642         fConservativeRasterSupport = true;
643     }
644 
645     fWireframeSupport = true;
646 
647     // We could actually query and get a max size for each config, however maxImageDimension2D will
648     // give the minimum max size across all configs. So for simplicity we will use that for now.
649     fMaxRenderTargetSize = std::min(properties.limits.maxImageDimension2D, (uint32_t)INT_MAX);
650     fMaxTextureSize = std::min(properties.limits.maxImageDimension2D, (uint32_t)INT_MAX);
651     if (fDriverBugWorkarounds.max_texture_size_limit_4096) {
652         fMaxTextureSize = std::min(fMaxTextureSize, 4096);
653     }
654 
655     // TODO: check if RT's larger than 4k incur a performance cost on ARM.
656     fMaxPreferredRenderTargetSize = fMaxRenderTargetSize;
657 
658     fMaxPushConstantsSize = std::min(properties.limits.maxPushConstantsSize, (uint32_t)INT_MAX);
659 
660     // Assuming since we will always map in the end to upload the data we might as well just map
661     // from the get go. There is no hard data to suggest this is faster or slower.
662     fBufferMapThreshold = 0;
663 
664     fMapBufferFlags = kCanMap_MapFlag | kSubset_MapFlag | kAsyncRead_MapFlag;
665 
666     fOversizedStencilSupport = true;
667 
668     if (extensions.hasExtension(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME, 2) &&
669         this->supportsPhysicalDeviceProperties2()) {
670 
671         VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT blendProps;
672         blendProps.sType =
673                 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT;
674         blendProps.pNext = nullptr;
675 
676         VkPhysicalDeviceProperties2 props;
677         props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
678         props.pNext = &blendProps;
679 
680         GR_VK_CALL(vkInterface, GetPhysicalDeviceProperties2(physDev, &props));
681 
682         if (blendProps.advancedBlendAllOperations == VK_TRUE) {
683             fShaderCaps->fAdvBlendEqInteraction = GrShaderCaps::kAutomatic_AdvBlendEqInteraction;
684 
685             auto blendFeatures =
686                 get_extension_feature_struct<VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT>(
687                     features,
688                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT);
689             if (blendFeatures && blendFeatures->advancedBlendCoherentOperations == VK_TRUE) {
690                 fBlendEquationSupport = kAdvancedCoherent_BlendEquationSupport;
691             } else {
692                 fBlendEquationSupport = kAdvanced_BlendEquationSupport;
693             }
694         }
695     }
696 
697     if (kARM_VkVendor == properties.vendorID || kHisi_VkVendor == properties.vendorID) {
698         fShouldCollapseSrcOverToSrcWhenAble = true;
699     }
700 
701     // We're seeing vkCmdClearAttachments take a lot of cpu time when clearing the color attachment.
702     // We really should only be getting in there for partial clears. So instead we will do all
703     // partial clears as draws.
704     if (kQualcomm_VkVendor == properties.vendorID) {
705         fPerformPartialClearsAsDraws = true;
706     }
707 
708     fSupportHpsBlur = (kHisi_VkVendor == properties.vendorID);
709 
710 #ifdef SUPPORT_OPAQUE_OPTIMIZATION
711     fSupportOpaqueRegion = (kHisi_VkVendor == properties.vendorID) && \
712         (properties.deviceID >= SK_OPAQUE_REGION_HARDWARE_SUPPORT_MIN_VERSION);
713 #endif
714 }
715 
initShaderCaps(const VkPhysicalDeviceProperties & properties,const VkPhysicalDeviceFeatures2 & features)716 void GrVkCaps::initShaderCaps(const VkPhysicalDeviceProperties& properties,
717                               const VkPhysicalDeviceFeatures2& features) {
718     GrShaderCaps* shaderCaps = fShaderCaps.get();
719     shaderCaps->fVersionDeclString = "#version 330\n";
720 
721     // Vulkan is based off ES 3.0 so the following should all be supported
722     shaderCaps->fUsesPrecisionModifiers = true;
723     shaderCaps->fFlatInterpolationSupport = true;
724     // Flat interpolation appears to be slow on Qualcomm GPUs. This was tested in GL and is assumed
725     // to be true with Vulkan as well.
726     shaderCaps->fPreferFlatInterpolation = kQualcomm_VkVendor != properties.vendorID;
727 
728     shaderCaps->fSampleMaskSupport = true;
729 
730     shaderCaps->fShaderDerivativeSupport = true;
731 
732     // ARM GPUs calculate `matrix * vector` in SPIR-V at full precision, even when the inputs are
733     // RelaxedPrecision. Rewriting the multiply as a sum of vector*scalar fixes this. (skia:11769)
734     shaderCaps->fRewriteMatrixVectorMultiply = (kARM_VkVendor == properties.vendorID || kHisi_VkVendor == properties.vendorID);
735 
736     shaderCaps->fDualSourceBlendingSupport = features.features.dualSrcBlend;
737 
738     shaderCaps->fIntegerSupport = true;
739     shaderCaps->fNonsquareMatrixSupport = true;
740     shaderCaps->fInverseHyperbolicSupport = true;
741     shaderCaps->fVertexIDSupport = true;
742     shaderCaps->fInfinitySupport = true;
743     shaderCaps->fNonconstantArrayIndexSupport = true;
744     shaderCaps->fBitManipulationSupport = true;
745 
746     // Assume the minimum precisions mandated by the SPIR-V spec.
747     shaderCaps->fFloatIs32Bits = true;
748     shaderCaps->fHalfIs32Bits = false;
749 
750     shaderCaps->fMaxFragmentSamplers = std::min(
751                                        std::min(properties.limits.maxPerStageDescriptorSampledImages,
752                                               properties.limits.maxPerStageDescriptorSamplers),
753                                               (uint32_t)INT_MAX);
754 }
755 
stencil_format_supported(const GrVkInterface * interface,VkPhysicalDevice physDev,VkFormat format)756 bool stencil_format_supported(const GrVkInterface* interface,
757                               VkPhysicalDevice physDev,
758                               VkFormat format) {
759     VkFormatProperties props;
760     memset(&props, 0, sizeof(VkFormatProperties));
761     GR_VK_CALL(interface, GetPhysicalDeviceFormatProperties(physDev, format, &props));
762     return SkToBool(VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT & props.optimalTilingFeatures);
763 }
764 
initStencilFormat(const GrVkInterface * interface,VkPhysicalDevice physDev)765 void GrVkCaps::initStencilFormat(const GrVkInterface* interface, VkPhysicalDevice physDev) {
766     if (stencil_format_supported(interface, physDev, VK_FORMAT_S8_UINT)) {
767         fPreferredStencilFormat = VK_FORMAT_S8_UINT;
768     } else if (stencil_format_supported(interface, physDev, VK_FORMAT_D24_UNORM_S8_UINT)) {
769         fPreferredStencilFormat = VK_FORMAT_D24_UNORM_S8_UINT;
770     } else {
771         SkASSERT(stencil_format_supported(interface, physDev, VK_FORMAT_D32_SFLOAT_S8_UINT));
772         fPreferredStencilFormat = VK_FORMAT_D32_SFLOAT_S8_UINT;
773     }
774 }
775 
format_is_srgb(VkFormat format)776 static bool format_is_srgb(VkFormat format) {
777     SkASSERT(GrVkFormatIsSupported(format));
778 
779     switch (format) {
780         case VK_FORMAT_R8G8B8A8_SRGB:
781             return true;
782         default:
783             return false;
784     }
785 }
786 
787 // These are all the valid VkFormats that we support in Skia. They are roughly ordered from most
788 // frequently used to least to improve look up times in arrays.
789 static constexpr VkFormat kVkFormats[] = {
790     VK_FORMAT_R8G8B8A8_UNORM,
791     VK_FORMAT_R8_UNORM,
792     VK_FORMAT_B8G8R8A8_UNORM,
793     VK_FORMAT_R5G6B5_UNORM_PACK16,
794     VK_FORMAT_R16G16B16A16_SFLOAT,
795     VK_FORMAT_R16_SFLOAT,
796     VK_FORMAT_R8G8B8_UNORM,
797     VK_FORMAT_R8G8_UNORM,
798     VK_FORMAT_A2B10G10R10_UNORM_PACK32,
799     VK_FORMAT_A2R10G10B10_UNORM_PACK32,
800     VK_FORMAT_B4G4R4A4_UNORM_PACK16,
801     VK_FORMAT_R4G4B4A4_UNORM_PACK16,
802     VK_FORMAT_R8G8B8A8_SRGB,
803     VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
804     VK_FORMAT_BC1_RGB_UNORM_BLOCK,
805     VK_FORMAT_BC1_RGBA_UNORM_BLOCK,
806     VK_FORMAT_R16_UNORM,
807     VK_FORMAT_R16G16_UNORM,
808     VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,
809     VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
810     VK_FORMAT_R16G16B16A16_UNORM,
811     VK_FORMAT_R16G16_SFLOAT,
812     VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
813     VK_FORMAT_ASTC_6x6_UNORM_BLOCK,
814     VK_FORMAT_ASTC_8x8_UNORM_BLOCK,
815 };
816 
setColorType(GrColorType colorType,std::initializer_list<VkFormat> formats)817 void GrVkCaps::setColorType(GrColorType colorType, std::initializer_list<VkFormat> formats) {
818 #ifdef SK_DEBUG
819     for (size_t i = 0; i < kNumVkFormats; ++i) {
820         const auto& formatInfo = fFormatTable[i];
821         for (int j = 0; j < formatInfo.fColorTypeInfoCount; ++j) {
822             const auto& ctInfo = formatInfo.fColorTypeInfos[j];
823             if (ctInfo.fColorType == colorType &&
824                 !SkToBool(ctInfo.fFlags & ColorTypeInfo::kWrappedOnly_Flag)) {
825                 bool found = false;
826                 for (auto it = formats.begin(); it != formats.end(); ++it) {
827                     if (kVkFormats[i] == *it) {
828                         found = true;
829                     }
830                 }
831                 SkASSERT(found);
832             }
833         }
834     }
835 #endif
836     int idx = static_cast<int>(colorType);
837     for (auto it = formats.begin(); it != formats.end(); ++it) {
838         const auto& info = this->getFormatInfo(*it);
839         for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
840             if (info.fColorTypeInfos[i].fColorType == colorType) {
841                 fColorTypeToFormatTable[idx] = *it;
842                 return;
843             }
844         }
845     }
846 }
847 
getFormatInfo(VkFormat format) const848 const GrVkCaps::FormatInfo& GrVkCaps::getFormatInfo(VkFormat format) const {
849     GrVkCaps* nonConstThis = const_cast<GrVkCaps*>(this);
850     return nonConstThis->getFormatInfo(format);
851 }
852 
getFormatInfo(VkFormat format)853 GrVkCaps::FormatInfo& GrVkCaps::getFormatInfo(VkFormat format) {
854     static_assert(SK_ARRAY_COUNT(kVkFormats) == GrVkCaps::kNumVkFormats,
855                   "Size of VkFormats array must match static value in header");
856     for (size_t i = 0; i < SK_ARRAY_COUNT(kVkFormats); ++i) {
857         if (kVkFormats[i] == format) {
858             return fFormatTable[i];
859         }
860     }
861     static FormatInfo kInvalidFormat;
862     return kInvalidFormat;
863 }
864 
initFormatTable(const GrVkInterface * interface,VkPhysicalDevice physDev,const VkPhysicalDeviceProperties & properties)865 void GrVkCaps::initFormatTable(const GrVkInterface* interface, VkPhysicalDevice physDev,
866                                const VkPhysicalDeviceProperties& properties) {
867     static_assert(SK_ARRAY_COUNT(kVkFormats) == GrVkCaps::kNumVkFormats,
868                   "Size of VkFormats array must match static value in header");
869 
870     std::fill_n(fColorTypeToFormatTable, kGrColorTypeCnt, VK_FORMAT_UNDEFINED);
871 
872     // Go through all the formats and init their support surface and data GrColorTypes.
873     // Format: VK_FORMAT_R8G8B8A8_UNORM
874     {
875         constexpr VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
876         auto& info = this->getFormatInfo(format);
877         info.init(interface, physDev, properties, format);
878         if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
879             info.fColorTypeInfoCount = 2;
880             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
881             int ctIdx = 0;
882             // Format: VK_FORMAT_R8G8B8A8_UNORM, Surface: kRGBA_8888
883             {
884                 constexpr GrColorType ct = GrColorType::kRGBA_8888;
885                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
886                 ctInfo.fColorType = ct;
887                 ctInfo.fTransferColorType = ct;
888                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
889             }
890             // Format: VK_FORMAT_R8G8B8A8_UNORM, Surface: kRGB_888x
891             {
892                 constexpr GrColorType ct = GrColorType::kRGB_888x;
893                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
894                 ctInfo.fColorType = ct;
895                 ctInfo.fTransferColorType = ct;
896                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
897                 ctInfo.fReadSwizzle = GrSwizzle::RGB1();
898             }
899         }
900     }
901 
902     // Format: VK_FORMAT_R8_UNORM
903     {
904         constexpr VkFormat format = VK_FORMAT_R8_UNORM;
905         auto& info = this->getFormatInfo(format);
906         info.init(interface, physDev, properties, format);
907         if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
908             info.fColorTypeInfoCount = 2;
909             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
910             int ctIdx = 0;
911             // Format: VK_FORMAT_R8_UNORM, Surface: kAlpha_8
912             {
913                 constexpr GrColorType ct = GrColorType::kAlpha_8;
914                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
915                 ctInfo.fColorType = ct;
916                 ctInfo.fTransferColorType = ct;
917                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
918                 ctInfo.fReadSwizzle = GrSwizzle("000r");
919                 ctInfo.fWriteSwizzle = GrSwizzle("a000");
920             }
921             // Format: VK_FORMAT_R8_UNORM, Surface: kGray_8
922             {
923                 constexpr GrColorType ct = GrColorType::kGray_8;
924                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
925                 ctInfo.fColorType = ct;
926                 ctInfo.fTransferColorType = ct;
927                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
928                 ctInfo.fReadSwizzle = GrSwizzle("rrr1");
929             }
930         }
931     }
932     // Format: VK_FORMAT_B8G8R8A8_UNORM
933     {
934         constexpr VkFormat format = VK_FORMAT_B8G8R8A8_UNORM;
935         auto& info = this->getFormatInfo(format);
936         info.init(interface, physDev, properties, format);
937         if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
938             info.fColorTypeInfoCount = 1;
939             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
940             int ctIdx = 0;
941             // Format: VK_FORMAT_B8G8R8A8_UNORM, Surface: kBGRA_8888
942             {
943                 constexpr GrColorType ct = GrColorType::kBGRA_8888;
944                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
945                 ctInfo.fColorType = ct;
946                 ctInfo.fTransferColorType = ct;
947                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
948             }
949         }
950     }
951     // Format: VK_FORMAT_R5G6B5_UNORM_PACK16
952     {
953         constexpr VkFormat format = VK_FORMAT_R5G6B5_UNORM_PACK16;
954         auto& info = this->getFormatInfo(format);
955         info.init(interface, physDev, properties, format);
956         if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
957             info.fColorTypeInfoCount = 1;
958             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
959             int ctIdx = 0;
960             // Format: VK_FORMAT_R5G6B5_UNORM_PACK16, Surface: kBGR_565
961             {
962                 constexpr GrColorType ct = GrColorType::kBGR_565;
963                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
964                 ctInfo.fColorType = ct;
965                 ctInfo.fTransferColorType = ct;
966                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
967             }
968         }
969     }
970     // Format: VK_FORMAT_R16G16B16A16_SFLOAT
971     {
972         constexpr VkFormat format = VK_FORMAT_R16G16B16A16_SFLOAT;
973         auto& info = this->getFormatInfo(format);
974         info.init(interface, physDev, properties, format);
975         if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
976             info.fColorTypeInfoCount = 2;
977             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
978             int ctIdx = 0;
979             // Format: VK_FORMAT_R16G16B16A16_SFLOAT, Surface: GrColorType::kRGBA_F16
980             {
981                 constexpr GrColorType ct = GrColorType::kRGBA_F16;
982                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
983                 ctInfo.fColorType = ct;
984                 ctInfo.fTransferColorType = ct;
985                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
986             }
987             // Format: VK_FORMAT_R16G16B16A16_SFLOAT, Surface: GrColorType::kRGBA_F16_Clamped
988             {
989                 constexpr GrColorType ct = GrColorType::kRGBA_F16_Clamped;
990                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
991                 ctInfo.fColorType = ct;
992                 ctInfo.fTransferColorType = ct;
993                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
994             }
995         }
996     }
997     // Format: VK_FORMAT_R16_SFLOAT
998     {
999         constexpr VkFormat format = VK_FORMAT_R16_SFLOAT;
1000         auto& info = this->getFormatInfo(format);
1001         info.init(interface, physDev, properties, format);
1002         if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1003             info.fColorTypeInfoCount = 1;
1004             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1005             int ctIdx = 0;
1006             // Format: VK_FORMAT_R16_SFLOAT, Surface: kAlpha_F16
1007             {
1008                 constexpr GrColorType ct = GrColorType::kAlpha_F16;
1009                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1010                 ctInfo.fColorType = ct;
1011                 ctInfo.fTransferColorType = ct;
1012                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
1013                 ctInfo.fReadSwizzle = GrSwizzle("000r");
1014                 ctInfo.fWriteSwizzle = GrSwizzle("a000");
1015             }
1016         }
1017     }
1018     // Format: VK_FORMAT_R8G8B8_UNORM
1019     {
1020         constexpr VkFormat format = VK_FORMAT_R8G8B8_UNORM;
1021         auto& info = this->getFormatInfo(format);
1022         info.init(interface, physDev, properties, format);
1023         if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1024             info.fColorTypeInfoCount = 1;
1025             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1026             int ctIdx = 0;
1027             // Format: VK_FORMAT_R8G8B8_UNORM, Surface: kRGB_888x
1028             {
1029                 constexpr GrColorType ct = GrColorType::kRGB_888x;
1030                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1031                 ctInfo.fColorType = ct;
1032                 // The Vulkan format is 3 bpp so we must convert to/from that when transferring.
1033                 ctInfo.fTransferColorType = GrColorType::kRGB_888;
1034                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
1035             }
1036         }
1037     }
1038     // Format: VK_FORMAT_R8G8_UNORM
1039     {
1040         constexpr VkFormat format = VK_FORMAT_R8G8_UNORM;
1041         auto& info = this->getFormatInfo(format);
1042         info.init(interface, physDev, properties, format);
1043         if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1044             info.fColorTypeInfoCount = 1;
1045             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1046             int ctIdx = 0;
1047             // Format: VK_FORMAT_R8G8_UNORM, Surface: kRG_88
1048             {
1049                 constexpr GrColorType ct = GrColorType::kRG_88;
1050                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1051                 ctInfo.fColorType = ct;
1052                 ctInfo.fTransferColorType = ct;
1053                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
1054             }
1055         }
1056     }
1057     // Format: VK_FORMAT_A2B10G10R10_UNORM_PACK32
1058     {
1059         constexpr VkFormat format = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
1060         auto& info = this->getFormatInfo(format);
1061         info.init(interface, physDev, properties, format);
1062         if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1063             info.fColorTypeInfoCount = 1;
1064             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1065             int ctIdx = 0;
1066             // Format: VK_FORMAT_A2B10G10R10_UNORM_PACK32, Surface: kRGBA_1010102
1067             {
1068                 constexpr GrColorType ct = GrColorType::kRGBA_1010102;
1069                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1070                 ctInfo.fColorType = ct;
1071                 ctInfo.fTransferColorType = ct;
1072                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
1073             }
1074         }
1075     }
1076     // Format: VK_FORMAT_A2R10G10B10_UNORM_PACK32
1077     {
1078         constexpr VkFormat format = VK_FORMAT_A2R10G10B10_UNORM_PACK32;
1079         auto& info = this->getFormatInfo(format);
1080         info.init(interface, physDev, properties, format);
1081         if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1082             info.fColorTypeInfoCount = 1;
1083             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1084             int ctIdx = 0;
1085             // Format: VK_FORMAT_A2R10G10B10_UNORM_PACK32, Surface: kBGRA_1010102
1086             {
1087                 constexpr GrColorType ct = GrColorType::kBGRA_1010102;
1088                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1089                 ctInfo.fColorType = ct;
1090                 ctInfo.fTransferColorType = ct;
1091                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
1092             }
1093         }
1094     }
1095     // Format: VK_FORMAT_B4G4R4A4_UNORM_PACK16
1096     {
1097         constexpr VkFormat format = VK_FORMAT_B4G4R4A4_UNORM_PACK16;
1098         auto& info = this->getFormatInfo(format);
1099         info.init(interface, physDev, properties, format);
1100         if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1101             info.fColorTypeInfoCount = 1;
1102             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1103             int ctIdx = 0;
1104             // Format: VK_FORMAT_B4G4R4A4_UNORM_PACK16, Surface: kABGR_4444
1105             {
1106                 constexpr GrColorType ct = GrColorType::kABGR_4444;
1107                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1108                 ctInfo.fColorType = ct;
1109                 ctInfo.fTransferColorType = ct;
1110                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
1111                 ctInfo.fReadSwizzle = GrSwizzle::BGRA();
1112                 ctInfo.fWriteSwizzle = GrSwizzle::BGRA();
1113             }
1114         }
1115     }
1116 
1117     // Format: VK_FORMAT_R4G4B4A4_UNORM_PACK16
1118     {
1119         constexpr VkFormat format = VK_FORMAT_R4G4B4A4_UNORM_PACK16;
1120         auto& info = this->getFormatInfo(format);
1121         info.init(interface, physDev, properties, format);
1122         if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1123             info.fColorTypeInfoCount = 1;
1124             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1125             int ctIdx = 0;
1126             // Format: VK_FORMAT_R4G4B4A4_UNORM_PACK16, Surface: kABGR_4444
1127             {
1128                 constexpr GrColorType ct = GrColorType::kABGR_4444;
1129                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1130                 ctInfo.fColorType = ct;
1131                 ctInfo.fTransferColorType = ct;
1132                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
1133             }
1134         }
1135     }
1136     // Format: VK_FORMAT_R8G8B8A8_SRGB
1137     {
1138         constexpr VkFormat format = VK_FORMAT_R8G8B8A8_SRGB;
1139         auto& info = this->getFormatInfo(format);
1140         info.init(interface, physDev, properties, format);
1141         if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1142             info.fColorTypeInfoCount = 1;
1143             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1144             int ctIdx = 0;
1145             // Format: VK_FORMAT_R8G8B8A8_SRGB, Surface: kRGBA_8888_SRGB
1146             {
1147                 constexpr GrColorType ct = GrColorType::kRGBA_8888_SRGB;
1148                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1149                 ctInfo.fColorType = ct;
1150                 ctInfo.fTransferColorType = ct;
1151                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
1152             }
1153         }
1154     }
1155     // Format: VK_FORMAT_R16_UNORM
1156     {
1157         constexpr VkFormat format = VK_FORMAT_R16_UNORM;
1158         auto& info = this->getFormatInfo(format);
1159         info.init(interface, physDev, properties, format);
1160         if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1161             info.fColorTypeInfoCount = 1;
1162             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1163             int ctIdx = 0;
1164             // Format: VK_FORMAT_R16_UNORM, Surface: kAlpha_16
1165             {
1166                 constexpr GrColorType ct = GrColorType::kAlpha_16;
1167                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1168                 ctInfo.fColorType = ct;
1169                 ctInfo.fTransferColorType = ct;
1170                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
1171                 ctInfo.fReadSwizzle = GrSwizzle("000r");
1172                 ctInfo.fWriteSwizzle = GrSwizzle("a000");
1173             }
1174         }
1175     }
1176     // Format: VK_FORMAT_R16G16_UNORM
1177     {
1178         constexpr VkFormat format = VK_FORMAT_R16G16_UNORM;
1179         auto& info = this->getFormatInfo(format);
1180         info.init(interface, physDev, properties, format);
1181         if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1182             info.fColorTypeInfoCount = 1;
1183             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1184             int ctIdx = 0;
1185             // Format: VK_FORMAT_R16G16_UNORM, Surface: kRG_1616
1186             {
1187                 constexpr GrColorType ct = GrColorType::kRG_1616;
1188                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1189                 ctInfo.fColorType = ct;
1190                 ctInfo.fTransferColorType = ct;
1191                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
1192             }
1193         }
1194     }
1195     // Format: VK_FORMAT_R16G16B16A16_UNORM
1196     {
1197         constexpr VkFormat format = VK_FORMAT_R16G16B16A16_UNORM;
1198         auto& info = this->getFormatInfo(format);
1199         info.init(interface, physDev, properties, format);
1200         if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1201             info.fColorTypeInfoCount = 1;
1202             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1203             int ctIdx = 0;
1204             // Format: VK_FORMAT_R16G16B16A16_UNORM, Surface: kRGBA_16161616
1205             {
1206                 constexpr GrColorType ct = GrColorType::kRGBA_16161616;
1207                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1208                 ctInfo.fColorType = ct;
1209                 ctInfo.fTransferColorType = ct;
1210                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
1211             }
1212         }
1213     }
1214     // Format: VK_FORMAT_R16G16_SFLOAT
1215     {
1216         constexpr VkFormat format = VK_FORMAT_R16G16_SFLOAT;
1217         auto& info = this->getFormatInfo(format);
1218         info.init(interface, physDev, properties, format);
1219         if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1220             info.fColorTypeInfoCount = 1;
1221             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1222             int ctIdx = 0;
1223             // Format: VK_FORMAT_R16G16_SFLOAT, Surface: kRG_F16
1224             {
1225                 constexpr GrColorType ct = GrColorType::kRG_F16;
1226                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1227                 ctInfo.fColorType = ct;
1228                 ctInfo.fTransferColorType = ct;
1229                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
1230             }
1231         }
1232     }
1233     // Format: VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM
1234     {
1235         constexpr VkFormat format = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM;
1236         auto& info = this->getFormatInfo(format);
1237         if (fSupportsYcbcrConversion) {
1238             info.init(interface, physDev, properties, format);
1239         }
1240         if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1241             info.fColorTypeInfoCount = 1;
1242             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1243             int ctIdx = 0;
1244             // Format: VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, Surface: kRGB_888x
1245             {
1246                 constexpr GrColorType ct = GrColorType::kRGB_888x;
1247                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1248                 ctInfo.fColorType = ct;
1249                 ctInfo.fTransferColorType = ct;
1250                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kWrappedOnly_Flag;
1251             }
1252         }
1253     }
1254     // Format: VK_FORMAT_G8_B8R8_2PLANE_420_UNORM
1255     {
1256         constexpr VkFormat format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
1257         auto& info = this->getFormatInfo(format);
1258         if (fSupportsYcbcrConversion) {
1259             info.init(interface, physDev, properties, format);
1260         }
1261         if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1262             info.fColorTypeInfoCount = 1;
1263             info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1264             int ctIdx = 0;
1265             // Format: VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, Surface: kRGB_888x
1266             {
1267                 constexpr GrColorType ct = GrColorType::kRGB_888x;
1268                 auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1269                 ctInfo.fColorType = ct;
1270                 ctInfo.fTransferColorType = ct;
1271                 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kWrappedOnly_Flag;
1272             }
1273         }
1274     }
1275     // Format: VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK
1276     {
1277         constexpr VkFormat format = VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
1278         auto& info = this->getFormatInfo(format);
1279         info.init(interface, physDev, properties, format);
1280         // Setting this to texel block size
1281         // No supported GrColorTypes.
1282     }
1283 
1284     // Format: VK_FORMAT_BC1_RGB_UNORM_BLOCK
1285     {
1286         constexpr VkFormat format = VK_FORMAT_BC1_RGB_UNORM_BLOCK;
1287         auto& info = this->getFormatInfo(format);
1288         info.init(interface, physDev, properties, format);
1289         // Setting this to texel block size
1290         // No supported GrColorTypes.
1291     }
1292 
1293     // Format: VK_FORMAT_BC1_RGBA_UNORM_BLOCK
1294     {
1295         constexpr VkFormat format = VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
1296         auto& info = this->getFormatInfo(format);
1297         info.init(interface, physDev, properties, format);
1298         // Setting this to texel block size
1299         // No supported GrColorTypes.
1300     }
1301 
1302     // Format: VK_FORMAT_ASTC_4x4_UNORM_BLOCK
1303     {
1304         constexpr VkFormat format = VK_FORMAT_ASTC_4x4_UNORM_BLOCK;
1305         auto& info = this->getFormatInfo(format);
1306         info.init(interface, physDev, properties, format);
1307         // Setting this to texel block size
1308         // No supported GrColorTypes.
1309     }
1310 
1311     // Format: VK_FORMAT_ASTC_6x6_UNORM_BLOCK
1312     {
1313         constexpr VkFormat format = VK_FORMAT_ASTC_6x6_UNORM_BLOCK;
1314         auto& info = this->getFormatInfo(format);
1315         info.init(interface, physDev, properties, format);
1316         // Setting this to texel block size
1317         // No supported GrColorTypes.
1318     }
1319 
1320     // Format: VK_FORMAT_ASTC_8x8_UNORM_BLOCK
1321     {
1322         constexpr VkFormat format = VK_FORMAT_ASTC_8x8_UNORM_BLOCK;
1323         auto& info = this->getFormatInfo(format);
1324         info.init(interface, physDev, properties, format);
1325         // Setting this to texel block size
1326         // No supported GrColorTypes.
1327     }
1328 
1329     ////////////////////////////////////////////////////////////////////////////
1330     // Map GrColorTypes (used for creating GrSurfaces) to VkFormats. The order in which the formats
1331     // are passed into the setColorType function indicates the priority in selecting which format
1332     // we use for a given GrcolorType.
1333 
1334     this->setColorType(GrColorType::kAlpha_8,          { VK_FORMAT_R8_UNORM });
1335     this->setColorType(GrColorType::kBGR_565,          { VK_FORMAT_R5G6B5_UNORM_PACK16 });
1336     this->setColorType(GrColorType::kABGR_4444,        { VK_FORMAT_R4G4B4A4_UNORM_PACK16,
1337                                                          VK_FORMAT_B4G4R4A4_UNORM_PACK16 });
1338     this->setColorType(GrColorType::kRGBA_8888,        { VK_FORMAT_R8G8B8A8_UNORM });
1339     this->setColorType(GrColorType::kRGBA_8888_SRGB,   { VK_FORMAT_R8G8B8A8_SRGB });
1340     this->setColorType(GrColorType::kRGB_888x,         { VK_FORMAT_R8G8B8_UNORM,
1341                                                          VK_FORMAT_R8G8B8A8_UNORM });
1342     this->setColorType(GrColorType::kRG_88,            { VK_FORMAT_R8G8_UNORM });
1343     this->setColorType(GrColorType::kBGRA_8888,        { VK_FORMAT_B8G8R8A8_UNORM });
1344     this->setColorType(GrColorType::kRGBA_1010102,     { VK_FORMAT_A2B10G10R10_UNORM_PACK32 });
1345     this->setColorType(GrColorType::kBGRA_1010102,     { VK_FORMAT_A2R10G10B10_UNORM_PACK32 });
1346     this->setColorType(GrColorType::kGray_8,           { VK_FORMAT_R8_UNORM });
1347     this->setColorType(GrColorType::kAlpha_F16,        { VK_FORMAT_R16_SFLOAT });
1348     this->setColorType(GrColorType::kRGBA_F16,         { VK_FORMAT_R16G16B16A16_SFLOAT });
1349     this->setColorType(GrColorType::kRGBA_F16_Clamped, { VK_FORMAT_R16G16B16A16_SFLOAT });
1350     this->setColorType(GrColorType::kAlpha_16,         { VK_FORMAT_R16_UNORM });
1351     this->setColorType(GrColorType::kRG_1616,          { VK_FORMAT_R16G16_UNORM });
1352     this->setColorType(GrColorType::kRGBA_16161616,    { VK_FORMAT_R16G16B16A16_UNORM });
1353     this->setColorType(GrColorType::kRG_F16,           { VK_FORMAT_R16G16_SFLOAT });
1354 }
1355 
InitFormatFlags(VkFormatFeatureFlags vkFlags,uint16_t * flags)1356 void GrVkCaps::FormatInfo::InitFormatFlags(VkFormatFeatureFlags vkFlags, uint16_t* flags) {
1357     if (SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT & vkFlags) &&
1358         SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT & vkFlags)) {
1359         *flags = *flags | kTexturable_Flag;
1360 
1361         // Ganesh assumes that all renderable surfaces are also texturable
1362         if (SkToBool(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT & vkFlags)) {
1363             *flags = *flags | kRenderable_Flag;
1364         }
1365     }
1366     // TODO: For Vk w/ VK_KHR_maintenance1 extension support, check
1367     //  VK_FORMAT_FEATURE_TRANSFER_[SRC|DST]_BIT_KHR explicitly to set copy flags
1368     //  Can do similar check for VK_KHR_sampler_ycbcr_conversion added bits
1369 
1370     if (SkToBool(VK_FORMAT_FEATURE_BLIT_SRC_BIT & vkFlags)) {
1371         *flags = *flags | kBlitSrc_Flag;
1372     }
1373 
1374     if (SkToBool(VK_FORMAT_FEATURE_BLIT_DST_BIT & vkFlags)) {
1375         *flags = *flags | kBlitDst_Flag;
1376     }
1377 }
1378 
initSampleCounts(const GrVkInterface * interface,VkPhysicalDevice physDev,const VkPhysicalDeviceProperties & physProps,VkFormat format)1379 void GrVkCaps::FormatInfo::initSampleCounts(const GrVkInterface* interface,
1380                                             VkPhysicalDevice physDev,
1381                                             const VkPhysicalDeviceProperties& physProps,
1382                                             VkFormat format) {
1383     VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
1384                               VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1385                               VK_IMAGE_USAGE_SAMPLED_BIT |
1386                               VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1387     VkImageFormatProperties properties;
1388     GR_VK_CALL(interface, GetPhysicalDeviceImageFormatProperties(physDev,
1389                                                                  format,
1390                                                                  VK_IMAGE_TYPE_2D,
1391                                                                  VK_IMAGE_TILING_OPTIMAL,
1392                                                                  usage,
1393                                                                  0,  // createFlags
1394                                                                  &properties));
1395     VkSampleCountFlags flags = properties.sampleCounts;
1396     if (flags & VK_SAMPLE_COUNT_1_BIT) {
1397         fColorSampleCounts.push_back(1);
1398     }
1399     if (kImagination_VkVendor == physProps.vendorID) {
1400         // MSAA does not work on imagination
1401         return;
1402     }
1403     if (kIntel_VkVendor == physProps.vendorID) {
1404         // MSAA doesn't work well on Intel GPUs chromium:527565, chromium:983926
1405         return;
1406     }
1407     if (flags & VK_SAMPLE_COUNT_2_BIT) {
1408         fColorSampleCounts.push_back(2);
1409     }
1410     if (flags & VK_SAMPLE_COUNT_4_BIT) {
1411         fColorSampleCounts.push_back(4);
1412     }
1413     if (flags & VK_SAMPLE_COUNT_8_BIT) {
1414         fColorSampleCounts.push_back(8);
1415     }
1416     if (flags & VK_SAMPLE_COUNT_16_BIT) {
1417         fColorSampleCounts.push_back(16);
1418     }
1419     // Standard sample locations are not defined for more than 16 samples, and we don't need more
1420     // than 16. Omit 32 and 64.
1421 }
1422 
init(const GrVkInterface * interface,VkPhysicalDevice physDev,const VkPhysicalDeviceProperties & properties,VkFormat format)1423 void GrVkCaps::FormatInfo::init(const GrVkInterface* interface,
1424                                 VkPhysicalDevice physDev,
1425                                 const VkPhysicalDeviceProperties& properties,
1426                                 VkFormat format) {
1427     VkFormatProperties props;
1428     memset(&props, 0, sizeof(VkFormatProperties));
1429     GR_VK_CALL(interface, GetPhysicalDeviceFormatProperties(physDev, format, &props));
1430     InitFormatFlags(props.linearTilingFeatures, &fLinearFlags);
1431     InitFormatFlags(props.optimalTilingFeatures, &fOptimalFlags);
1432     if (fOptimalFlags & kRenderable_Flag) {
1433         this->initSampleCounts(interface, physDev, properties, format);
1434     }
1435 }
1436 
1437 // For many checks in caps, we need to know whether the GrBackendFormat is external or not. If it is
1438 // external the VkFormat will be VK_NULL_HANDLE which is not handled by our various format
1439 // capability checks.
backend_format_is_external(const GrBackendFormat & format)1440 static bool backend_format_is_external(const GrBackendFormat& format) {
1441     const GrVkYcbcrConversionInfo* ycbcrInfo = format.getVkYcbcrConversionInfo();
1442     SkASSERT(ycbcrInfo);
1443 
1444     // All external formats have a valid ycbcrInfo used for sampling and a non zero external format.
1445     if (ycbcrInfo->isValid() && ycbcrInfo->fExternalFormat != 0) {
1446 #ifdef SK_DEBUG
1447         VkFormat vkFormat;
1448         SkAssertResult(format.asVkFormat(&vkFormat));
1449         SkASSERT(vkFormat == VK_FORMAT_UNDEFINED);
1450 #endif
1451         return true;
1452     }
1453     return false;
1454 }
1455 
isFormatSRGB(const GrBackendFormat & format) const1456 bool GrVkCaps::isFormatSRGB(const GrBackendFormat& format) const {
1457     VkFormat vkFormat;
1458     if (!format.asVkFormat(&vkFormat)) {
1459         return false;
1460     }
1461     if (backend_format_is_external(format)) {
1462         return false;
1463     }
1464 
1465     return format_is_srgb(vkFormat);
1466 }
1467 
isFormatTexturable(const GrBackendFormat & format,GrTextureType) const1468 bool GrVkCaps::isFormatTexturable(const GrBackendFormat& format, GrTextureType) const {
1469     VkFormat vkFormat;
1470     if (!format.asVkFormat(&vkFormat)) {
1471         return false;
1472     }
1473     if (backend_format_is_external(format)) {
1474         // We can always texture from an external format (assuming we have the ycbcr conversion
1475         // info which we require to be passed in).
1476         return true;
1477     }
1478     return this->isVkFormatTexturable(vkFormat);
1479 }
1480 
isVkFormatTexturable(VkFormat format) const1481 bool GrVkCaps::isVkFormatTexturable(VkFormat format) const {
1482     const FormatInfo& info = this->getFormatInfo(format);
1483     return SkToBool(FormatInfo::kTexturable_Flag & info.fOptimalFlags);
1484 }
1485 
isFormatAsColorTypeRenderable(GrColorType ct,const GrBackendFormat & format,int sampleCount) const1486 bool GrVkCaps::isFormatAsColorTypeRenderable(GrColorType ct, const GrBackendFormat& format,
1487                                              int sampleCount) const {
1488     if (!this->isFormatRenderable(format, sampleCount)) {
1489         return false;
1490     }
1491     VkFormat vkFormat;
1492     if (!format.asVkFormat(&vkFormat)) {
1493         return false;
1494     }
1495     const auto& info = this->getFormatInfo(vkFormat);
1496     if (!SkToBool(info.colorTypeFlags(ct) & ColorTypeInfo::kRenderable_Flag)) {
1497         return false;
1498     }
1499     return true;
1500 }
1501 
isFormatRenderable(const GrBackendFormat & format,int sampleCount) const1502 bool GrVkCaps::isFormatRenderable(const GrBackendFormat& format, int sampleCount) const {
1503     VkFormat vkFormat;
1504     if (!format.asVkFormat(&vkFormat)) {
1505         return false;
1506     }
1507     return this->isFormatRenderable(vkFormat, sampleCount);
1508 }
1509 
isFormatRenderable(VkFormat format,int sampleCount) const1510 bool GrVkCaps::isFormatRenderable(VkFormat format, int sampleCount) const {
1511     return sampleCount <= this->maxRenderTargetSampleCount(format);
1512 }
1513 
getRenderTargetSampleCount(int requestedCount,const GrBackendFormat & format) const1514 int GrVkCaps::getRenderTargetSampleCount(int requestedCount,
1515                                          const GrBackendFormat& format) const {
1516     VkFormat vkFormat;
1517     if (!format.asVkFormat(&vkFormat)) {
1518         return 0;
1519     }
1520 
1521     return this->getRenderTargetSampleCount(requestedCount, vkFormat);
1522 }
1523 
getRenderTargetSampleCount(int requestedCount,VkFormat format) const1524 int GrVkCaps::getRenderTargetSampleCount(int requestedCount, VkFormat format) const {
1525     requestedCount = std::max(1, requestedCount);
1526 
1527     const FormatInfo& info = this->getFormatInfo(format);
1528 
1529     int count = info.fColorSampleCounts.count();
1530 
1531     if (!count) {
1532         return 0;
1533     }
1534 
1535     if (1 == requestedCount) {
1536         SkASSERT(info.fColorSampleCounts.count() && info.fColorSampleCounts[0] == 1);
1537         return 1;
1538     }
1539 
1540     for (int i = 0; i < count; ++i) {
1541         if (info.fColorSampleCounts[i] >= requestedCount) {
1542             return info.fColorSampleCounts[i];
1543         }
1544     }
1545     return 0;
1546 }
1547 
maxRenderTargetSampleCount(const GrBackendFormat & format) const1548 int GrVkCaps::maxRenderTargetSampleCount(const GrBackendFormat& format) const {
1549     VkFormat vkFormat;
1550     if (!format.asVkFormat(&vkFormat)) {
1551         return 0;
1552     }
1553     return this->maxRenderTargetSampleCount(vkFormat);
1554 }
1555 
maxRenderTargetSampleCount(VkFormat format) const1556 int GrVkCaps::maxRenderTargetSampleCount(VkFormat format) const {
1557     const FormatInfo& info = this->getFormatInfo(format);
1558 
1559     const auto& table = info.fColorSampleCounts;
1560     if (!table.count()) {
1561         return 0;
1562     }
1563     return table[table.count() - 1];
1564 }
1565 
align_to_4(size_t v)1566 static inline size_t align_to_4(size_t v) {
1567     switch (v & 0b11) {
1568         // v is already a multiple of 4.
1569         case 0:     return v;
1570         // v is a multiple of 2 but not 4.
1571         case 2:     return 2 * v;
1572         // v is not a multiple of 2.
1573         default:    return 4 * v;
1574     }
1575 }
1576 
supportedWritePixelsColorType(GrColorType surfaceColorType,const GrBackendFormat & surfaceFormat,GrColorType srcColorType) const1577 GrCaps::SupportedWrite GrVkCaps::supportedWritePixelsColorType(GrColorType surfaceColorType,
1578                                                                const GrBackendFormat& surfaceFormat,
1579                                                                GrColorType srcColorType) const {
1580     VkFormat vkFormat;
1581     if (!surfaceFormat.asVkFormat(&vkFormat)) {
1582         return {GrColorType::kUnknown, 0};
1583     }
1584 
1585     // We don't support the ability to upload to external formats or formats that require a ycbcr
1586     // sampler. In general these types of formats are only used for sampling in a shader.
1587     if (backend_format_is_external(surfaceFormat) || GrVkFormatNeedsYcbcrSampler(vkFormat)) {
1588         return {GrColorType::kUnknown, 0};
1589     }
1590 
1591     // The VkBufferImageCopy bufferOffset field must be both a multiple of 4 and of a single texel.
1592     size_t offsetAlignment = align_to_4(GrVkFormatBytesPerBlock(vkFormat));
1593 
1594     const auto& info = this->getFormatInfo(vkFormat);
1595     for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1596         const auto& ctInfo = info.fColorTypeInfos[i];
1597         if (ctInfo.fColorType == surfaceColorType) {
1598             return {ctInfo.fTransferColorType, offsetAlignment};
1599         }
1600     }
1601     return {GrColorType::kUnknown, 0};
1602 }
1603 
surfaceSupportsReadPixels(const GrSurface * surface) const1604 GrCaps::SurfaceReadPixelsSupport GrVkCaps::surfaceSupportsReadPixels(
1605         const GrSurface* surface) const {
1606     if (surface->isProtected()) {
1607         return SurfaceReadPixelsSupport::kUnsupported;
1608     }
1609     if (auto tex = static_cast<const GrVkTexture*>(surface->asTexture())) {
1610         auto texImage = tex->textureImage();
1611         if (!texImage) {
1612             return SurfaceReadPixelsSupport::kUnsupported;
1613         }
1614         // We can't directly read from a VkImage that has a ycbcr sampler.
1615         if (texImage->ycbcrConversionInfo().isValid()) {
1616             return SurfaceReadPixelsSupport::kCopyToTexture2D;
1617         }
1618         // We can't directly read from a compressed format
1619         if (GrVkFormatIsCompressed(texImage->imageFormat())) {
1620             return SurfaceReadPixelsSupport::kCopyToTexture2D;
1621         }
1622         return SurfaceReadPixelsSupport::kSupported;
1623     } else if (auto rt = surface->asRenderTarget()) {
1624         if (rt->numSamples() > 1) {
1625             return SurfaceReadPixelsSupport::kCopyToTexture2D;
1626         }
1627         return SurfaceReadPixelsSupport::kSupported;
1628     }
1629     return SurfaceReadPixelsSupport::kUnsupported;
1630 }
1631 
transferColorType(VkFormat vkFormat,GrColorType surfaceColorType) const1632 GrColorType GrVkCaps::transferColorType(VkFormat vkFormat, GrColorType surfaceColorType) const {
1633     const auto& info = this->getFormatInfo(vkFormat);
1634     for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1635         if (info.fColorTypeInfos[i].fColorType == surfaceColorType) {
1636             return info.fColorTypeInfos[i].fTransferColorType;
1637         }
1638     }
1639     return GrColorType::kUnknown;
1640 }
1641 
onSurfaceSupportsWritePixels(const GrSurface * surface) const1642 bool GrVkCaps::onSurfaceSupportsWritePixels(const GrSurface* surface) const {
1643     if (auto rt = surface->asRenderTarget()) {
1644         return rt->numSamples() <= 1 && SkToBool(surface->asTexture());
1645     }
1646     // We can't write to a texture that has a ycbcr sampler.
1647     if (auto tex = static_cast<const GrVkTexture*>(surface->asTexture())) {
1648         auto texImage = tex->textureImage();
1649         if (!texImage) {
1650             return false;
1651         }
1652         // We can't directly read from a VkImage that has a ycbcr sampler.
1653         if (texImage->ycbcrConversionInfo().isValid()) {
1654             return false;
1655         }
1656     }
1657     return true;
1658 }
1659 
onAreColorTypeAndFormatCompatible(GrColorType ct,const GrBackendFormat & format) const1660 bool GrVkCaps::onAreColorTypeAndFormatCompatible(GrColorType ct,
1661                                                  const GrBackendFormat& format) const {
1662     VkFormat vkFormat;
1663     if (!format.asVkFormat(&vkFormat)) {
1664         return false;
1665     }
1666     const GrVkYcbcrConversionInfo* ycbcrInfo = format.getVkYcbcrConversionInfo();
1667     SkASSERT(ycbcrInfo);
1668 
1669     if (ycbcrInfo->isValid() && !GrVkFormatNeedsYcbcrSampler(vkFormat)) {
1670         // Format may be undefined for external images, which are required to have YCbCr conversion.
1671         if (VK_FORMAT_UNDEFINED == vkFormat && ycbcrInfo->fExternalFormat != 0) {
1672             return true;
1673         }
1674         return false;
1675     }
1676 
1677     const auto& info = this->getFormatInfo(vkFormat);
1678     for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1679         if (info.fColorTypeInfos[i].fColorType == ct) {
1680             return true;
1681         }
1682     }
1683     return false;
1684 }
1685 
onGetDefaultBackendFormat(GrColorType ct) const1686 GrBackendFormat GrVkCaps::onGetDefaultBackendFormat(GrColorType ct) const {
1687     VkFormat format = this->getFormatFromColorType(ct);
1688     if (format == VK_FORMAT_UNDEFINED) {
1689         return {};
1690     }
1691     return GrBackendFormat::MakeVk(format);
1692 }
1693 
onSupportsDynamicMSAA(const GrRenderTargetProxy * rtProxy) const1694 bool GrVkCaps::onSupportsDynamicMSAA(const GrRenderTargetProxy* rtProxy) const {
1695     // We must be able to use the rtProxy as an input attachment to load into the discardable msaa
1696     // attachment. Also the rtProxy should have a sample count of 1 so that it can be used as a
1697     // resolve attachment.
1698     return this->supportsDiscardableMSAAForDMSAA() &&
1699            rtProxy->supportsVkInputAttachment() &&
1700            rtProxy->numSamples() == 1;
1701 }
1702 
renderTargetSupportsDiscardableMSAA(const GrVkRenderTarget * rt) const1703 bool GrVkCaps::renderTargetSupportsDiscardableMSAA(const GrVkRenderTarget* rt) const {
1704     return rt->resolveAttachment() &&
1705            rt->resolveAttachment()->supportsInputAttachmentUsage() &&
1706            ((rt->numSamples() > 1 && this->preferDiscardableMSAAAttachment()) ||
1707             (rt->numSamples() == 1 && this->supportsDiscardableMSAAForDMSAA()));
1708 }
1709 
programInfoWillUseDiscardableMSAA(const GrProgramInfo & programInfo) const1710 bool GrVkCaps::programInfoWillUseDiscardableMSAA(const GrProgramInfo& programInfo) const {
1711     return programInfo.targetHasVkResolveAttachmentWithInput() &&
1712            programInfo.numSamples() > 1 &&
1713            ((programInfo.targetsNumSamples() > 1 && this->preferDiscardableMSAAAttachment()) ||
1714             (programInfo.targetsNumSamples() == 1 && this->supportsDiscardableMSAAForDMSAA()));
1715 }
1716 
getBackendFormatFromCompressionType(SkImage::CompressionType compressionType) const1717 GrBackendFormat GrVkCaps::getBackendFormatFromCompressionType(
1718         SkImage::CompressionType compressionType) const {
1719     switch (compressionType) {
1720         case SkImage::CompressionType::kNone:
1721             return {};
1722         case SkImage::CompressionType::kETC2_RGB8_UNORM:
1723             if (this->isVkFormatTexturable(VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK)) {
1724                 return GrBackendFormat::MakeVk(VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK);
1725             }
1726             return {};
1727         case SkImage::CompressionType::kBC1_RGB8_UNORM:
1728             if (this->isVkFormatTexturable(VK_FORMAT_BC1_RGB_UNORM_BLOCK)) {
1729                 return GrBackendFormat::MakeVk(VK_FORMAT_BC1_RGB_UNORM_BLOCK);
1730             }
1731             return {};
1732         case SkImage::CompressionType::kBC1_RGBA8_UNORM:
1733             if (this->isVkFormatTexturable(VK_FORMAT_BC1_RGBA_UNORM_BLOCK)) {
1734                 return GrBackendFormat::MakeVk(VK_FORMAT_BC1_RGBA_UNORM_BLOCK);
1735             }
1736             return {};
1737         case SkImage::CompressionType::kASTC_RGBA8_4x4:
1738             if (this->isVkFormatTexturable(VK_FORMAT_ASTC_4x4_UNORM_BLOCK)) {
1739                 return GrBackendFormat::MakeVk(VK_FORMAT_ASTC_4x4_UNORM_BLOCK);
1740             }
1741             return {};
1742         case SkImage::CompressionType::kASTC_RGBA8_6x6:
1743             if (this->isVkFormatTexturable(VK_FORMAT_ASTC_6x6_UNORM_BLOCK)) {
1744                 return GrBackendFormat::MakeVk(VK_FORMAT_ASTC_6x6_UNORM_BLOCK);
1745             }
1746             return {};
1747         case SkImage::CompressionType::kASTC_RGBA8_8x8:
1748             if (this->isVkFormatTexturable(VK_FORMAT_ASTC_8x8_UNORM_BLOCK)) {
1749                 return GrBackendFormat::MakeVk(VK_FORMAT_ASTC_8x8_UNORM_BLOCK);
1750             }
1751             return {};
1752     }
1753 
1754     SkUNREACHABLE;
1755 }
1756 
onGetReadSwizzle(const GrBackendFormat & format,GrColorType colorType) const1757 GrSwizzle GrVkCaps::onGetReadSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
1758     VkFormat vkFormat;
1759     SkAssertResult(format.asVkFormat(&vkFormat));
1760     const auto* ycbcrInfo = format.getVkYcbcrConversionInfo();
1761     SkASSERT(ycbcrInfo);
1762     if (ycbcrInfo->isValid() && ycbcrInfo->fExternalFormat != 0) {
1763         // We allow these to work with any color type and never swizzle. See
1764         // onAreColorTypeAndFormatCompatible.
1765         return GrSwizzle{"rgba"};
1766     }
1767 
1768     const auto& info = this->getFormatInfo(vkFormat);
1769     for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1770         const auto& ctInfo = info.fColorTypeInfos[i];
1771         if (ctInfo.fColorType == colorType) {
1772             return ctInfo.fReadSwizzle;
1773         }
1774     }
1775     SkDEBUGFAILF("Illegal color type (%d) and format (%d) combination.",
1776                  (int)colorType, (int)vkFormat);
1777     return {};
1778 }
1779 
getWriteSwizzle(const GrBackendFormat & format,GrColorType colorType) const1780 GrSwizzle GrVkCaps::getWriteSwizzle(const GrBackendFormat& format, GrColorType colorType) const {
1781     VkFormat vkFormat;
1782     SkAssertResult(format.asVkFormat(&vkFormat));
1783     const auto& info = this->getFormatInfo(vkFormat);
1784     for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1785         const auto& ctInfo = info.fColorTypeInfos[i];
1786         if (ctInfo.fColorType == colorType) {
1787             return ctInfo.fWriteSwizzle;
1788         }
1789     }
1790     SkDEBUGFAILF("Illegal color type (%d) and format (%d) combination.",
1791                  (int)colorType, (int)vkFormat);
1792     return {};
1793 }
1794 
onGetDstSampleFlagsForProxy(const GrRenderTargetProxy * rt) const1795 GrDstSampleFlags GrVkCaps::onGetDstSampleFlagsForProxy(const GrRenderTargetProxy* rt) const {
1796     bool isMSAAWithResolve = rt->numSamples() > 1 && rt->asTextureProxy();
1797     // TODO: Currently if we have an msaa rt with a resolve, the supportsVkInputAttachment call
1798     // references whether the resolve is supported as an input attachment. We need to add a check to
1799     // allow checking the color attachment (msaa or not) supports input attachment specifically.
1800     if (!isMSAAWithResolve && rt->supportsVkInputAttachment()) {
1801         return GrDstSampleFlags::kRequiresTextureBarrier | GrDstSampleFlags::kAsInputAttachment;
1802     }
1803     return GrDstSampleFlags::kNone;
1804 }
1805 
computeFormatKey(const GrBackendFormat & format) const1806 uint64_t GrVkCaps::computeFormatKey(const GrBackendFormat& format) const {
1807     VkFormat vkFormat;
1808     SkAssertResult(format.asVkFormat(&vkFormat));
1809 
1810 #ifdef SK_DEBUG
1811     // We should never be trying to compute a key for an external format
1812     const GrVkYcbcrConversionInfo* ycbcrInfo = format.getVkYcbcrConversionInfo();
1813     SkASSERT(ycbcrInfo);
1814     SkASSERT(!ycbcrInfo->isValid() || ycbcrInfo->fExternalFormat == 0);
1815 #endif
1816 
1817     // A VkFormat has a size of 64 bits.
1818     return (uint64_t)vkFormat;
1819 }
1820 
onSupportedReadPixelsColorType(GrColorType srcColorType,const GrBackendFormat & srcBackendFormat,GrColorType dstColorType) const1821 GrCaps::SupportedRead GrVkCaps::onSupportedReadPixelsColorType(
1822         GrColorType srcColorType, const GrBackendFormat& srcBackendFormat,
1823         GrColorType dstColorType) const {
1824     VkFormat vkFormat;
1825     if (!srcBackendFormat.asVkFormat(&vkFormat)) {
1826         return {GrColorType::kUnknown, 0};
1827     }
1828 
1829     if (GrVkFormatNeedsYcbcrSampler(vkFormat)) {
1830         return {GrColorType::kUnknown, 0};
1831     }
1832 
1833     SkImage::CompressionType compression = GrBackendFormatToCompressionType(srcBackendFormat);
1834     if (compression != SkImage::CompressionType::kNone) {
1835         return { SkCompressionTypeIsOpaque(compression) ? GrColorType::kRGB_888x
1836                                                         : GrColorType::kRGBA_8888, 0 };
1837     }
1838 
1839     // The VkBufferImageCopy bufferOffset field must be both a multiple of 4 and of a single texel.
1840     size_t offsetAlignment = align_to_4(GrVkFormatBytesPerBlock(vkFormat));
1841 
1842     const auto& info = this->getFormatInfo(vkFormat);
1843     for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1844         const auto& ctInfo = info.fColorTypeInfos[i];
1845         if (ctInfo.fColorType == srcColorType) {
1846             return {ctInfo.fTransferColorType, offsetAlignment};
1847         }
1848     }
1849     return {GrColorType::kUnknown, 0};
1850 }
1851 
getFragmentUniformBinding() const1852 int GrVkCaps::getFragmentUniformBinding() const {
1853     return GrVkUniformHandler::kUniformBinding;
1854 }
1855 
getFragmentUniformSet() const1856 int GrVkCaps::getFragmentUniformSet() const {
1857     return GrVkUniformHandler::kUniformBufferDescSet;
1858 }
1859 
addExtraSamplerKey(GrProcessorKeyBuilder * b,GrSamplerState samplerState,const GrBackendFormat & format) const1860 void GrVkCaps::addExtraSamplerKey(GrProcessorKeyBuilder* b,
1861                                   GrSamplerState samplerState,
1862                                   const GrBackendFormat& format) const {
1863     const GrVkYcbcrConversionInfo* ycbcrInfo = format.getVkYcbcrConversionInfo();
1864     if (!ycbcrInfo) {
1865         return;
1866     }
1867 
1868     GrVkSampler::Key key = GrVkSampler::GenerateKey(samplerState, *ycbcrInfo);
1869 
1870     constexpr size_t numInts = (sizeof(key) + 3) / 4;
1871     uint32_t tmp[numInts];
1872     memcpy(tmp, &key, sizeof(key));
1873 
1874     for (size_t i = 0; i < numInts; ++i) {
1875         b->add32(tmp[i]);
1876     }
1877 }
1878 
1879 /**
1880  * For Vulkan we want to cache the entire VkPipeline for reuse of draws. The Desc here holds all
1881  * the information needed to differentiate one pipeline from another.
1882  *
1883  * The GrProgramDesc contains all the information need to create the actual shaders for the
1884  * pipeline.
1885  *
1886  * For Vulkan we need to add to the GrProgramDesc to include the rest of the state on the
1887  * pipline. This includes stencil settings, blending information, render pass format, draw face
1888  * information, and primitive type. Note that some state is set dynamically on the pipeline for
1889  * each draw  and thus is not included in this descriptor. This includes the viewport, scissor,
1890  * and blend constant.
1891  */
makeDesc(GrRenderTarget * rt,const GrProgramInfo & programInfo,ProgramDescOverrideFlags overrideFlags) const1892 GrProgramDesc GrVkCaps::makeDesc(GrRenderTarget* rt,
1893                                  const GrProgramInfo& programInfo,
1894                                  ProgramDescOverrideFlags overrideFlags) const {
1895     GrProgramDesc desc;
1896     GrProgramDesc::Build(&desc, programInfo, *this);
1897 
1898     GrProcessorKeyBuilder b(desc.key());
1899 
1900     // This will become part of the sheared off key used to persistently cache
1901     // the SPIRV code. It needs to be added right after the base key so that,
1902     // when the base-key is sheared off, the shearing code can include it in the
1903     // reduced key (c.f. the +4s in the SkData::MakeWithCopy calls in
1904     // GrVkPipelineStateBuilder.cpp).
1905     b.add32(GrVkGpu::kShader_PersistentCacheKeyType);
1906 
1907     GrVkRenderPass::SelfDependencyFlags selfDepFlags = GrVkRenderPass::SelfDependencyFlags::kNone;
1908     if (programInfo.renderPassBarriers() & GrXferBarrierFlags::kBlend) {
1909         selfDepFlags |= GrVkRenderPass::SelfDependencyFlags::kForNonCoherentAdvBlend;
1910     }
1911     if (programInfo.renderPassBarriers() & GrXferBarrierFlags::kTexture) {
1912         selfDepFlags |= GrVkRenderPass::SelfDependencyFlags::kForInputAttachment;
1913     }
1914 
1915     bool needsResolve = this->programInfoWillUseDiscardableMSAA(programInfo);
1916 
1917     bool forceLoadFromResolve =
1918             overrideFlags & GrCaps::ProgramDescOverrideFlags::kVulkanHasResolveLoadSubpass;
1919     SkASSERT(!forceLoadFromResolve || needsResolve);
1920 
1921     GrVkRenderPass::LoadFromResolve loadFromResolve = GrVkRenderPass::LoadFromResolve::kNo;
1922     if (needsResolve && (programInfo.colorLoadOp() == GrLoadOp::kLoad || forceLoadFromResolve)) {
1923         loadFromResolve = GrVkRenderPass::LoadFromResolve::kLoad;
1924     }
1925 
1926     if (rt) {
1927         GrVkRenderTarget* vkRT = (GrVkRenderTarget*) rt;
1928 
1929         SkASSERT(!needsResolve || (vkRT->resolveAttachment() &&
1930                                    vkRT->resolveAttachment()->supportsInputAttachmentUsage()));
1931 
1932         bool needsStencil = programInfo.needsStencil() || programInfo.isStencilEnabled();
1933         // TODO: support failure in getSimpleRenderPass
1934         auto rp = vkRT->getSimpleRenderPass(needsResolve, needsStencil, selfDepFlags,
1935                                             loadFromResolve);
1936         SkASSERT(rp);
1937         rp->genKey(&b);
1938 
1939 #ifdef SK_DEBUG
1940         if (!rp->isExternal()) {
1941             // This is to ensure ReconstructAttachmentsDescriptor keeps matching
1942             // getSimpleRenderPass' result
1943             GrVkRenderPass::AttachmentsDescriptor attachmentsDescriptor;
1944             GrVkRenderPass::AttachmentFlags attachmentFlags;
1945             GrVkRenderTarget::ReconstructAttachmentsDescriptor(*this, programInfo,
1946                                                                &attachmentsDescriptor,
1947                                                                &attachmentFlags);
1948             SkASSERT(rp->isCompatible(attachmentsDescriptor, attachmentFlags, selfDepFlags,
1949                                       loadFromResolve));
1950         }
1951 #endif
1952     } else {
1953         GrVkRenderPass::AttachmentsDescriptor attachmentsDescriptor;
1954         GrVkRenderPass::AttachmentFlags attachmentFlags;
1955         GrVkRenderTarget::ReconstructAttachmentsDescriptor(*this, programInfo,
1956                                                            &attachmentsDescriptor,
1957                                                            &attachmentFlags);
1958 
1959         // kExternal_AttachmentFlag is only set for wrapped secondary command buffers - which
1960         // will always go through the above 'rt' path (i.e., we can always pass 0 as the final
1961         // parameter to GenKey).
1962         GrVkRenderPass::GenKey(&b, attachmentFlags, attachmentsDescriptor, selfDepFlags,
1963                                loadFromResolve, 0);
1964     }
1965 
1966     GrStencilSettings stencil = programInfo.nonGLStencilSettings();
1967     stencil.genKey(&b, true);
1968 
1969     programInfo.pipeline().genKey(&b, *this);
1970     b.add32(programInfo.numSamples());
1971 
1972     // Vulkan requires the full primitive type as part of its key
1973     b.add32(programInfo.primitiveTypeKey());
1974 
1975     b.flush();
1976     return desc;
1977 }
1978 
getExtraSurfaceFlagsForDeferredRT() const1979 GrInternalSurfaceFlags GrVkCaps::getExtraSurfaceFlagsForDeferredRT() const {
1980     // We always create vulkan RT with the input attachment flag;
1981     return GrInternalSurfaceFlags::kVkRTSupportsInputAttachment;
1982 }
1983 
getPushConstantStageFlags() const1984 VkShaderStageFlags GrVkCaps::getPushConstantStageFlags() const {
1985     VkShaderStageFlags stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
1986     return stageFlags;
1987 }
1988 
supportsHpsBlur(const GrSurfaceProxyView * proxyViewPtr) const1989 bool GrVkCaps::supportsHpsBlur(const GrSurfaceProxyView* proxyViewPtr) const
1990 {
1991     if (proxyViewPtr == nullptr) {
1992         return false;
1993     }
1994     if (proxyViewPtr->asTextureProxy() == nullptr) {
1995         return false;
1996     }
1997     const GrBackendFormat& grBackendFormat = proxyViewPtr->asTextureProxy()->backendFormat();
1998     VkFormat format;
1999     if (!grBackendFormat.asVkFormat(&format)) {
2000         return false;
2001     }
2002     if (((format == VkFormat::VK_FORMAT_R8G8B8A8_UNORM)
2003         || (format == VkFormat::VK_FORMAT_R8G8B8_UNORM)
2004         || (format == VkFormat::VK_FORMAT_R16G16B16A16_SFLOAT))
2005         && fSupportHpsBlur) {
2006         return true;
2007     }
2008     return false;
2009 }
2010 
2011 #ifdef SUPPORT_OPAQUE_OPTIMIZATION
supportsOpaqueRegion() const2012 bool GrVkCaps::supportsOpaqueRegion() const
2013 {
2014     static const bool opaqueRegionEnabled =
2015         OHOS::system::GetIntParameter("persist.sys.graphic.openOpaqueRegion", 1) != 0;
2016     return fSupportOpaqueRegion && opaqueRegionEnabled;
2017 }
2018 #endif
2019 
2020 #if GR_TEST_UTILS
getTestingCombinations() const2021 std::vector<GrCaps::TestFormatColorTypeCombination> GrVkCaps::getTestingCombinations() const {
2022     std::vector<GrCaps::TestFormatColorTypeCombination> combos = {
2023         { GrColorType::kAlpha_8,          GrBackendFormat::MakeVk(VK_FORMAT_R8_UNORM)             },
2024         { GrColorType::kBGR_565,          GrBackendFormat::MakeVk(VK_FORMAT_R5G6B5_UNORM_PACK16)  },
2025         { GrColorType::kABGR_4444,        GrBackendFormat::MakeVk(VK_FORMAT_R4G4B4A4_UNORM_PACK16)},
2026         { GrColorType::kABGR_4444,        GrBackendFormat::MakeVk(VK_FORMAT_B4G4R4A4_UNORM_PACK16)},
2027         { GrColorType::kRGBA_8888,        GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8A8_UNORM)       },
2028         { GrColorType::kRGBA_8888_SRGB,   GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8A8_SRGB)        },
2029         { GrColorType::kRGB_888x,         GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8A8_UNORM)       },
2030         { GrColorType::kRGB_888x,         GrBackendFormat::MakeVk(VK_FORMAT_R8G8B8_UNORM)         },
2031         { GrColorType::kRG_88,            GrBackendFormat::MakeVk(VK_FORMAT_R8G8_UNORM)           },
2032         { GrColorType::kBGRA_8888,        GrBackendFormat::MakeVk(VK_FORMAT_B8G8R8A8_UNORM)       },
2033         { GrColorType::kRGBA_1010102,  GrBackendFormat::MakeVk(VK_FORMAT_A2B10G10R10_UNORM_PACK32)},
2034         { GrColorType::kBGRA_1010102,  GrBackendFormat::MakeVk(VK_FORMAT_A2R10G10B10_UNORM_PACK32)},
2035         { GrColorType::kGray_8,           GrBackendFormat::MakeVk(VK_FORMAT_R8_UNORM)             },
2036         { GrColorType::kAlpha_F16,        GrBackendFormat::MakeVk(VK_FORMAT_R16_SFLOAT)           },
2037         { GrColorType::kRGBA_F16,         GrBackendFormat::MakeVk(VK_FORMAT_R16G16B16A16_SFLOAT)  },
2038         { GrColorType::kRGBA_F16_Clamped, GrBackendFormat::MakeVk(VK_FORMAT_R16G16B16A16_SFLOAT)  },
2039         { GrColorType::kAlpha_16,         GrBackendFormat::MakeVk(VK_FORMAT_R16_UNORM)            },
2040         { GrColorType::kRG_1616,          GrBackendFormat::MakeVk(VK_FORMAT_R16G16_UNORM)         },
2041         { GrColorType::kRGBA_16161616,    GrBackendFormat::MakeVk(VK_FORMAT_R16G16B16A16_UNORM)   },
2042         { GrColorType::kRG_F16,           GrBackendFormat::MakeVk(VK_FORMAT_R16G16_SFLOAT)        },
2043         // These two compressed formats both have an effective colorType of kRGB_888x
2044         { GrColorType::kRGB_888x,       GrBackendFormat::MakeVk(VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK)},
2045         { GrColorType::kRGB_888x,         GrBackendFormat::MakeVk(VK_FORMAT_BC1_RGB_UNORM_BLOCK)  },
2046         { GrColorType::kRGBA_8888,        GrBackendFormat::MakeVk(VK_FORMAT_BC1_RGBA_UNORM_BLOCK) },
2047         { GrColorType::kRGBA_8888,        GrBackendFormat::MakeVk(VK_FORMAT_ASTC_4x4_UNORM_BLOCK) },
2048         { GrColorType::kRGBA_8888,        GrBackendFormat::MakeVk(VK_FORMAT_ASTC_6x6_UNORM_BLOCK) },
2049         { GrColorType::kRGBA_8888,        GrBackendFormat::MakeVk(VK_FORMAT_ASTC_8x8_UNORM_BLOCK) },
2050     };
2051 
2052     return combos;
2053 }
2054 #endif
2055