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