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