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