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