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