Coverage Report

Created: 2024-05-20 07:14

/src/skia/src/gpu/ganesh/vk/GrVkCaps.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2015 Google Inc.
3
 *
4
 * Use of this source code is governed by a BSD-style license that can be
5
 * found in the LICENSE file.
6
 */
7
8
#include "src/gpu/ganesh/vk/GrVkCaps.h"
9
10
#include <memory>
11
12
#include "include/core/SkTextureCompressionType.h"
13
#include "include/gpu/GrBackendSurface.h"
14
#include "include/gpu/GrContextOptions.h"
15
#include "include/gpu/ganesh/vk/GrVkBackendSurface.h"
16
#include "include/gpu/vk/GrVkBackendContext.h"
17
#include "include/gpu/vk/VulkanExtensions.h"
18
#include "src/core/SkCompressedDataUtils.h"
19
#include "src/gpu/KeyBuilder.h"
20
#include "src/gpu/ganesh/GrBackendUtils.h"
21
#include "src/gpu/ganesh/GrProgramDesc.h"
22
#include "src/gpu/ganesh/GrRenderTarget.h"
23
#include "src/gpu/ganesh/GrRenderTargetProxy.h"
24
#include "src/gpu/ganesh/GrShaderCaps.h"
25
#include "src/gpu/ganesh/GrStencilSettings.h"
26
#include "src/gpu/ganesh/GrUtil.h"
27
#include "src/gpu/ganesh/SkGr.h"
28
#include "src/gpu/ganesh/TestFormatColorTypeCombination.h"
29
#include "src/gpu/ganesh/vk/GrVkGpu.h"
30
#include "src/gpu/ganesh/vk/GrVkImage.h"
31
#include "src/gpu/ganesh/vk/GrVkRenderTarget.h"
32
#include "src/gpu/ganesh/vk/GrVkTexture.h"
33
#include "src/gpu/ganesh/vk/GrVkUniformHandler.h"
34
#include "src/gpu/ganesh/vk/GrVkUtil.h"
35
#include "src/gpu/vk/VulkanInterface.h"
36
#include "src/gpu/vk/VulkanUtilsPriv.h"
37
38
#ifdef SK_BUILD_FOR_ANDROID
39
#include <sys/system_properties.h>
40
#endif
41
42
GrVkCaps::GrVkCaps(const GrContextOptions& contextOptions,
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
0
        : INHERITED(contextOptions) {
51
    /**************************************************************************
52
     * GrCaps fields
53
     **************************************************************************/
54
0
    fMipmapSupport = true;   // always available in Vulkan
55
0
    fAnisoSupport = true;   // always available in Vulkan
56
0
    fNPOTTextureTileSupport = true;  // always available in Vulkan
57
0
    fReuseScratchTextures = true; //TODO: figure this out
58
0
    fGpuTracingSupport = false; //TODO: figure this out
59
0
    fOversizedStencilSupport = false; //TODO: figure this out
60
0
    fDrawInstancedSupport = true;
61
62
0
    fSemaphoreSupport = true;   // always available in Vulkan
63
0
    fBackendSemaphoreSupport = true;
64
0
    fFinishedProcAsyncCallbackSupport = true;
65
0
    fCrossContextTextureSupport = true;
66
0
    fHalfFloatVertexAttributeSupport = true;
67
68
    // We always copy in/out of a transfer buffer so it's trivial to support row bytes.
69
0
    fReadPixelsRowBytesSupport = true;
70
0
    fWritePixelsRowBytesSupport = true;
71
72
0
    fTransferFromBufferToTextureSupport = true;
73
0
    fTransferFromSurfaceToBufferSupport = true;
74
0
    fTransferFromBufferToBufferSupport  = true;
75
76
0
    fMaxRenderTargetSize = 4096; // minimum required by spec
77
0
    fMaxTextureSize = 4096; // minimum required by spec
78
79
0
    fDynamicStateArrayGeometryProcessorTextureSupport = true;
80
81
0
    fTextureBarrierSupport = true;
82
83
0
    fShaderCaps = std::make_unique<GrShaderCaps>();
84
85
0
    this->init(contextOptions, vkInterface, physDev, features, physicalDeviceVersion, extensions,
86
0
               isProtected);
87
0
}
88
89
namespace {
90
/**
91
 * This comes from section 37.1.6 of the Vulkan spec. Format is
92
 * (<bits>|<tag>)_<block_size>_<texels_per_block>.
93
 */
94
enum 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
107
0
static FormatCompatibilityClass format_compatibility_class(VkFormat format) {
108
0
    switch (format) {
109
0
        case VK_FORMAT_B8G8R8A8_UNORM:
110
0
        case VK_FORMAT_R8G8B8A8_UNORM:
111
0
        case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
112
0
        case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
113
0
        case VK_FORMAT_R8G8B8A8_SRGB:
114
0
        case VK_FORMAT_R16G16_UNORM:
115
0
        case VK_FORMAT_R16G16_SFLOAT:
116
0
            return FormatCompatibilityClass::k32_4_1;
117
118
0
        case VK_FORMAT_R8_UNORM:
119
0
            return FormatCompatibilityClass::k8_1_1;
120
121
0
        case VK_FORMAT_R5G6B5_UNORM_PACK16:
122
0
        case VK_FORMAT_B5G6R5_UNORM_PACK16:
123
0
        case VK_FORMAT_R16_SFLOAT:
124
0
        case VK_FORMAT_R8G8_UNORM:
125
0
        case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
126
0
        case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
127
0
        case VK_FORMAT_R16_UNORM:
128
0
            return FormatCompatibilityClass::k16_2_1;
129
130
0
        case VK_FORMAT_R16G16B16A16_SFLOAT:
131
0
        case VK_FORMAT_R16G16B16A16_UNORM:
132
0
            return FormatCompatibilityClass::k64_8_1;
133
134
0
        case VK_FORMAT_R8G8B8_UNORM:
135
0
            return FormatCompatibilityClass::k24_3_1;
136
137
0
        case VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16:
138
0
            return FormatCompatibilityClass::k10x6_64_6_1;
139
140
0
        case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
141
0
            return FormatCompatibilityClass::kETC2_RGB_8_16;
142
143
0
        case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
144
0
            return FormatCompatibilityClass::kBC1_RGB_8_16_1;
145
146
0
        case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
147
0
            return FormatCompatibilityClass::kBC1_RGBA_8_16;
148
149
0
        default:
150
0
            SK_ABORT("Unsupported VkFormat");
151
0
    }
152
0
}
153
154
bool GrVkCaps::canCopyImage(VkFormat dstFormat, int dstSampleCnt, bool dstHasYcbcr,
155
0
                            VkFormat srcFormat, int srcSampleCnt, bool srcHasYcbcr) const {
156
0
    if ((dstSampleCnt > 1 || srcSampleCnt > 1) && dstSampleCnt != srcSampleCnt) {
157
0
        return false;
158
0
    }
159
160
0
    if (dstHasYcbcr || srcHasYcbcr) {
161
0
        return false;
162
0
    }
163
164
    // We require that all Vulkan GrSurfaces have been created with transfer_dst and transfer_src
165
    // as image usage flags.
166
0
    return format_compatibility_class(srcFormat) == format_compatibility_class(dstFormat);
167
0
}
168
169
bool GrVkCaps::canCopyAsBlit(VkFormat dstFormat, int dstSampleCnt, bool dstIsLinear,
170
                             bool dstHasYcbcr, VkFormat srcFormat, int srcSampleCnt,
171
0
                             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
0
    if (!this->formatCanBeDstofBlit(dstFormat, dstIsLinear) ||
175
0
        !this->formatCanBeSrcofBlit(srcFormat, srcIsLinear)) {
176
0
        return false;
177
0
    }
178
179
    // We cannot blit images that are multisampled. Will need to figure out if we can blit the
180
    // resolved msaa though.
181
0
    if (dstSampleCnt > 1 || srcSampleCnt > 1) {
182
0
        return false;
183
0
    }
184
185
0
    if (dstHasYcbcr || srcHasYcbcr) {
186
0
        return false;
187
0
    }
188
189
0
    return true;
190
0
}
191
192
bool GrVkCaps::canCopyAsResolve(VkFormat dstFormat, int dstSampleCnt, bool dstHasYcbcr,
193
0
                                VkFormat srcFormat, int srcSampleCnt, bool srcHasYcbcr) const {
194
    // The src surface must be multisampled.
195
0
    if (srcSampleCnt <= 1) {
196
0
        return false;
197
0
    }
198
199
    // The dst must not be multisampled.
200
0
    if (dstSampleCnt > 1) {
201
0
        return false;
202
0
    }
203
204
    // Surfaces must have the same format.
205
0
    if (srcFormat != dstFormat) {
206
0
        return false;
207
0
    }
208
209
0
    if (dstHasYcbcr || srcHasYcbcr) {
210
0
        return false;
211
0
    }
212
213
0
    return true;
214
0
}
215
216
bool GrVkCaps::onCanCopySurface(const GrSurfaceProxy* dst, const SkIRect& dstRect,
217
0
                                const GrSurfaceProxy* src, const SkIRect& srcRect) const {
218
0
    if (src->isProtected() == GrProtected::kYes && dst->isProtected() != GrProtected::kYes) {
219
0
        return false;
220
0
    }
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
0
    bool srcIsLinear = false;
227
0
    bool dstIsLinear = false;
228
229
0
    int dstSampleCnt = 0;
230
0
    int srcSampleCnt = 0;
231
0
    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
0
        if (rtProxy->wrapsVkSecondaryCB()) {
236
0
            return false;
237
0
        }
238
0
        if (this->preferDiscardableMSAAAttachment() && dst->asTextureProxy() &&
239
0
            rtProxy->supportsVkInputAttachment()) {
240
0
            dstSampleCnt = 1;
241
0
        } else {
242
0
            dstSampleCnt = rtProxy->numSamples();
243
0
        }
244
0
    }
245
0
    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
0
        if (rtProxy->wrapsVkSecondaryCB()) {
250
0
            return false;
251
0
        }
252
0
        if (this->preferDiscardableMSAAAttachment() && src->asTextureProxy() &&
253
0
            rtProxy->supportsVkInputAttachment()) {
254
0
            srcSampleCnt = 1;
255
0
        } else {
256
0
            srcSampleCnt = rtProxy->numSamples();
257
0
        }
258
0
    }
259
0
    SkASSERT((dstSampleCnt > 0) == SkToBool(dst->asRenderTargetProxy()));
260
0
    SkASSERT((srcSampleCnt > 0) == SkToBool(src->asRenderTargetProxy()));
261
262
0
    bool dstHasYcbcr = false;
263
0
    if (auto ycbcr = GrBackendFormats::GetVkYcbcrConversionInfo(dst->backendFormat())) {
264
0
        if (ycbcr->isValid()) {
265
0
            dstHasYcbcr = true;
266
0
        }
267
0
    }
268
269
0
    bool srcHasYcbcr = false;
270
0
    if (auto ycbcr = GrBackendFormats::GetVkYcbcrConversionInfo(src->backendFormat())) {
271
0
        if (ycbcr->isValid()) {
272
0
            srcHasYcbcr = true;
273
0
        }
274
0
    }
275
276
0
    VkFormat dstFormat, srcFormat;
277
0
    SkAssertResult(GrBackendFormats::AsVkFormat(dst->backendFormat(), &dstFormat));
278
0
    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
0
    const bool copyScales = srcRect.size() != dstRect.size();
283
0
    if (!copyScales && (this->canCopyImage(dstFormat, dstSampleCnt, dstHasYcbcr,
284
0
                                           srcFormat, srcSampleCnt, srcHasYcbcr) ||
285
0
                        this->canCopyAsResolve(dstFormat, dstSampleCnt, dstHasYcbcr,
286
0
                                               srcFormat, srcSampleCnt, srcHasYcbcr))) {
287
0
        return true;
288
0
    }
289
0
    return this->canCopyAsBlit(dstFormat, dstSampleCnt, dstIsLinear, dstHasYcbcr,
290
0
                               srcFormat, srcSampleCnt, srcIsLinear, srcHasYcbcr);
291
292
0
}
Unexecuted instantiation: GrVkCaps::onCanCopySurface(GrSurfaceProxy const*, SkIRect const&, GrSurfaceProxy const*, SkIRect const&) const
Unexecuted instantiation: GrVkCaps::onCanCopySurface(GrSurfaceProxy const*, SkIRect const&, GrSurfaceProxy const*, SkIRect const&) const
293
294
void 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
0
                    GrProtected isProtected) {
301
0
    VkPhysicalDeviceProperties properties;
302
0
    GR_VK_CALL(vkInterface, GetPhysicalDeviceProperties(physDev, &properties));
303
304
0
#if defined(GR_TEST_UTILS)
305
0
    this->setDeviceName(properties.deviceName);
306
0
#endif
307
308
0
    VkPhysicalDeviceMemoryProperties memoryProperties;
309
0
    GR_VK_CALL(vkInterface, GetPhysicalDeviceMemoryProperties(physDev, &memoryProperties));
310
311
0
    SkASSERT(physicalDeviceVersion <= properties.apiVersion);
312
313
0
    if (extensions.hasExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME, 1)) {
314
0
        fSupportsSwapchain = true;
315
0
    }
316
317
0
    if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
318
0
        extensions.hasExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 1)) {
319
0
        fSupportsPhysicalDeviceProperties2 = true;
320
0
    }
321
322
0
    if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
323
0
        extensions.hasExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, 1)) {
324
0
        fSupportsMemoryRequirements2 = true;
325
0
    }
326
327
0
    if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
328
0
        extensions.hasExtension(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME, 1)) {
329
0
        fSupportsBindMemory2 = true;
330
0
    }
331
332
0
    if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
333
0
        extensions.hasExtension(VK_KHR_MAINTENANCE1_EXTENSION_NAME, 1)) {
334
0
        fSupportsMaintenance1 = true;
335
0
    }
336
337
0
    if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
338
0
        extensions.hasExtension(VK_KHR_MAINTENANCE2_EXTENSION_NAME, 1)) {
339
0
        fSupportsMaintenance2 = true;
340
0
    }
341
342
0
    if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
343
0
        extensions.hasExtension(VK_KHR_MAINTENANCE3_EXTENSION_NAME, 1)) {
344
0
        fSupportsMaintenance3 = true;
345
0
    }
346
347
0
    if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
348
0
        (extensions.hasExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, 1) &&
349
0
         this->supportsMemoryRequirements2())) {
350
0
        fSupportsDedicatedAllocation = true;
351
0
    }
352
353
0
    if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
354
0
        (extensions.hasExtension(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, 1) &&
355
0
         this->supportsPhysicalDeviceProperties2() &&
356
0
         extensions.hasExtension(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME, 1) &&
357
0
         this->supportsDedicatedAllocation())) {
358
0
        fSupportsExternalMemory = true;
359
0
    }
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(
365
            VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME, 2) &&
366
       /* extensions.hasExtension(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME, 1) &&*/
367
        this->supportsExternalMemory() &&
368
        this->supportsBindMemory2()) {
369
        fSupportsAndroidHWBExternalMemory = true;
370
        fSupportsAHardwareBufferImages = true;
371
    }
372
#endif
373
374
0
    auto ycbcrFeatures = skgpu::GetExtensionFeatureStruct<
375
0
            VkPhysicalDeviceSamplerYcbcrConversionFeatures>(
376
0
                    features,
377
0
                    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES);
378
0
    if (ycbcrFeatures && ycbcrFeatures->samplerYcbcrConversion &&
379
0
        (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
380
0
         (extensions.hasExtension(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, 1) &&
381
0
          this->supportsMaintenance1() && this->supportsBindMemory2() &&
382
0
          this->supportsMemoryRequirements2() && this->supportsPhysicalDeviceProperties2()))) {
383
0
        fSupportsYcbcrConversion = true;
384
0
    }
385
386
    // We always push back the default GrVkYcbcrConversionInfo so that the case of no conversion
387
    // will return a key of 0.
388
0
    fYcbcrInfos.push_back(GrVkYcbcrConversionInfo());
389
390
0
    if ((isProtected == GrProtected::kYes) &&
391
0
        (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0))) {
392
0
        fSupportsProtectedContent = true;
393
0
        fAvoidUpdateBuffers = true;
394
0
        fShouldAlwaysUseDedicatedImageMemory = true;
395
0
    }
396
397
0
    if (extensions.hasExtension(VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME, 1)) {
398
0
        fSupportsDRMFormatModifiers = true;
399
0
    }
400
401
0
    if (extensions.hasExtension(VK_EXT_DEVICE_FAULT_EXTENSION_NAME, 1)) {
402
0
        fSupportsDeviceFaultInfo = true;
403
0
    }
404
405
0
    fMaxInputAttachmentDescriptors = properties.limits.maxDescriptorSetInputAttachments;
406
407
0
    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
0
    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.
424
0
        fPreferDiscardableMSAAAttachment = !fSupportsProtectedContent;
425
0
        fSupportsMemorylessAttachments = !fSupportsProtectedContent;
426
0
    }
427
428
0
    this->initGrCaps(vkInterface, physDev, properties, memoryProperties, features, extensions);
429
0
    this->initShaderCaps(properties, features);
430
431
0
    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.
436
0
        fPreferFullscreenClears = true;
437
0
    }
438
439
0
    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
0
        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
0
        fShouldPersistentlyMapCpuToGpuBuffers = false;
450
0
    }
451
452
0
    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
0
        fAvoidUpdateBuffers = true;
456
0
    }
457
458
0
    fNativeDrawIndirectSupport = features.features.drawIndirectFirstInstance;
459
0
    if (properties.vendorID == kQualcomm_VkVendor) {
460
        // Indirect draws seem slow on QC. Disable until we can investigate. http://skbug.com/11139
461
0
        fNativeDrawIndirectSupport = false;
462
0
    }
463
464
0
    if (fNativeDrawIndirectSupport) {
465
0
        fMaxDrawIndirectDrawCount = properties.limits.maxDrawIndirectCount;
466
0
        SkASSERT(fMaxDrawIndirectDrawCount == 1 || features.features.multiDrawIndirect);
467
0
    }
468
469
0
#ifdef SK_BUILD_FOR_UNIX
470
0
    if (kNvidia_VkVendor == properties.vendorID) {
471
        // On nvidia linux we see a big perf regression when not using dedicated image allocations.
472
0
        fShouldAlwaysUseDedicatedImageMemory = true;
473
0
    }
474
0
#endif
475
476
0
    this->initFormatTable(contextOptions, vkInterface, physDev, properties, features, extensions);
477
0
    this->initStencilFormat(vkInterface, physDev);
478
479
0
    if (contextOptions.fMaxCachedVulkanSecondaryCommandBuffers >= 0) {
480
0
        fMaxPerPoolCachedSecondaryCommandBuffers =
481
0
                contextOptions.fMaxCachedVulkanSecondaryCommandBuffers;
482
0
    }
483
484
0
    if (!contextOptions.fDisableDriverCorrectnessWorkarounds) {
485
0
        this->applyDriverCorrectnessWorkarounds(properties);
486
0
    }
487
488
0
    this->finishInitialization(contextOptions);
489
0
}
Unexecuted instantiation: GrVkCaps::init(GrContextOptions const&, skgpu::VulkanInterface const*, VkPhysicalDevice_T*, VkPhysicalDeviceFeatures2 const&, unsigned int, skgpu::VulkanExtensions const&, skgpu::Protected)
Unexecuted instantiation: GrVkCaps::init(GrContextOptions const&, skgpu::VulkanInterface const*, VkPhysicalDevice_T*, VkPhysicalDeviceFeatures2 const&, unsigned int, skgpu::VulkanExtensions const&, skgpu::Protected)
490
491
0
void 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
0
    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
0
    if (fSupportsProtectedContent && (kQualcomm_VkVendor == properties.vendorID)) {
516
0
        if (androidAPIVersion <= 28) {
517
0
            fSupportsProtectedContent = false;
518
0
        }
519
0
    }
520
521
    // On Mali galaxy s7 we see lots of rendering issues when we suballocate VkImages.
522
0
    if (kARM_VkVendor == properties.vendorID && androidAPIVersion <= 28) {
523
0
        fShouldAlwaysUseDedicatedImageMemory = true;
524
0
    }
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
0
    if (kARM_VkVendor == properties.vendorID && androidAPIVersion <= 28) {
529
0
        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.
532
0
        fTextureBarrierSupport = false;
533
0
        fBlendEquationSupport = kBasic_BlendEquationSupport;
534
0
    }
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
0
    if (properties.vendorID == kQualcomm_VkVendor && androidAPIVersion <= 28) {
540
0
        fPreferDiscardableMSAAAttachment = false;
541
0
        fSupportsDiscardableMSAAForDMSAA = false;
542
0
    }
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
0
    if (kARM_VkVendor == properties.vendorID) {
547
0
        fShaderCaps->fPerlinNoiseRoundingFix = true;
548
0
    }
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
0
    if (kQualcomm_VkVendor == properties.vendorID || kAMD_VkVendor == properties.vendorID) {
554
0
        fMustInvalidatePrimaryCmdBufferStateAfterClearAttachments = true;
555
0
    }
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
0
    if (properties.vendorID == kQualcomm_VkVendor ||
562
0
        properties.vendorID == kARM_VkVendor ||
563
0
        (properties.vendorID == kGoogle_VkVendor &&
564
0
         properties.deviceID == kSwiftshader_DeviceID)) {
565
0
        fMustLoadFullImageWithDiscardableMSAA = true;
566
0
    }
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
0
    if (properties.vendorID == kGoogle_VkVendor && properties.deviceID == kSwiftshader_DeviceID) {
574
0
        fReuseScratchBuffers = false;
575
0
    }
576
577
    ////////////////////////////////////////////////////////////////////////////
578
    // GrCaps workarounds
579
    ////////////////////////////////////////////////////////////////////////////
580
581
0
    if (kARM_VkVendor == properties.vendorID) {
582
0
        fAvoidWritePixelsFastPath = true; // bugs.skia.org/8064
583
0
    }
584
585
    // AMD advertises support for MAX_UINT vertex input attributes, but in reality only supports 32.
586
0
    if (kAMD_VkVendor == properties.vendorID) {
587
0
        fMaxVertexAttributes = std::min(fMaxVertexAttributes, 32);
588
0
    }
589
590
    // Adreno devices fail when trying to read the dest using an input attachment and texture
591
    // barriers.
592
0
    if (kQualcomm_VkVendor == properties.vendorID) {
593
0
        fTextureBarrierSupport = false;
594
0
    }
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) {
609
        fTextureBarrierSupport = false;
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
0
    if (properties.vendorID == kARM_VkVendor && androidAPIVersion <= 28) {
616
0
        fNativeDrawIndirectSupport = false;
617
0
    }
618
619
    ////////////////////////////////////////////////////////////////////////////
620
    // GrShaderCaps workarounds
621
    ////////////////////////////////////////////////////////////////////////////
622
623
0
    if (kImagination_VkVendor == properties.vendorID) {
624
0
        fShaderCaps->fAtan2ImplementedAsAtanYOverX = true;
625
0
    }
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
0
    if (kARM_VkVendor == properties.vendorID) {
630
0
        fShaderCaps->fRewriteMatrixVectorMultiply = true;
631
0
    }
632
0
}
633
634
void GrVkCaps::initGrCaps(const skgpu::VulkanInterface* vkInterface,
635
                          VkPhysicalDevice physDev,
636
                          const VkPhysicalDeviceProperties& properties,
637
                          const VkPhysicalDeviceMemoryProperties& memoryProperties,
638
                          const VkPhysicalDeviceFeatures2& features,
639
0
                          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
0
    static const uint32_t kMaxVertexAttributes = 64;
645
0
    fMaxVertexAttributes = std::min(properties.limits.maxVertexInputAttributes,
646
0
                                    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
0
    if (properties.limits.standardSampleLocations) {
652
0
        fSampleLocationsSupport = true;
653
0
    }
654
655
0
    if (extensions.hasExtension(VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME, 1)) {
656
0
        fConservativeRasterSupport = true;
657
0
    }
658
659
0
    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
0
    fMaxRenderTargetSize = std::min(properties.limits.maxImageDimension2D, (uint32_t)INT_MAX);
664
0
    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.
667
0
    fMaxPreferredRenderTargetSize = fMaxRenderTargetSize;
668
669
0
    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.
673
0
    fBufferMapThreshold = 0;
674
675
0
    fMapBufferFlags = kCanMap_MapFlag | kSubset_MapFlag | kAsyncRead_MapFlag;
676
677
0
    fOversizedStencilSupport = true;
678
679
0
    if (extensions.hasExtension(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME, 2) &&
680
0
        this->supportsPhysicalDeviceProperties2()) {
681
682
0
        VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT blendProps;
683
0
        blendProps.sType =
684
0
                VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT;
685
0
        blendProps.pNext = nullptr;
686
687
0
        VkPhysicalDeviceProperties2 props;
688
0
        props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
689
0
        props.pNext = &blendProps;
690
691
0
        GR_VK_CALL(vkInterface, GetPhysicalDeviceProperties2(physDev, &props));
692
693
0
        if (blendProps.advancedBlendAllOperations == VK_TRUE) {
694
0
            fShaderCaps->fAdvBlendEqInteraction = GrShaderCaps::kAutomatic_AdvBlendEqInteraction;
695
696
0
            auto blendFeatures = skgpu::GetExtensionFeatureStruct<
697
0
                    VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT>(
698
0
                            features,
699
0
                            VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT
700
0
                    );
701
0
            if (blendFeatures && blendFeatures->advancedBlendCoherentOperations == VK_TRUE) {
702
0
                fBlendEquationSupport = kAdvancedCoherent_BlendEquationSupport;
703
0
            } else {
704
0
                fBlendEquationSupport = kAdvanced_BlendEquationSupport;
705
0
            }
706
0
        }
707
0
    }
708
709
0
    if (kARM_VkVendor == properties.vendorID) {
710
0
        fShouldCollapseSrcOverToSrcWhenAble = true;
711
0
    }
712
0
}
713
714
void GrVkCaps::initShaderCaps(const VkPhysicalDeviceProperties& properties,
715
0
                              const VkPhysicalDeviceFeatures2& features) {
716
0
    GrShaderCaps* shaderCaps = fShaderCaps.get();
717
0
    shaderCaps->fVersionDeclString = "#version 330\n";
718
719
    // Ganesh + Vulkan always emits `sk_Clockwise` to avoid some Adreno rendering errors.
720
0
    shaderCaps->fMustDeclareFragmentFrontFacing = true;
721
722
    // Vulkan is based off ES 3.0 so the following should all be supported
723
0
    shaderCaps->fUsesPrecisionModifiers = true;
724
0
    shaderCaps->fFlatInterpolationSupport = true;
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
0
    shaderCaps->fPreferFlatInterpolation = kQualcomm_VkVendor != properties.vendorID;
728
729
0
    shaderCaps->fSampleMaskSupport = true;
730
731
0
    shaderCaps->fShaderDerivativeSupport = true;
732
0
    shaderCaps->fExplicitTextureLodSupport = true;
733
734
0
    shaderCaps->fDualSourceBlendingSupport = features.features.dualSrcBlend;
735
736
0
    shaderCaps->fIntegerSupport = true;
737
0
    shaderCaps->fNonsquareMatrixSupport = true;
738
0
    shaderCaps->fInverseHyperbolicSupport = true;
739
0
    shaderCaps->fVertexIDSupport = true;
740
0
    shaderCaps->fInfinitySupport = true;
741
0
    shaderCaps->fNonconstantArrayIndexSupport = true;
742
0
    shaderCaps->fBitManipulationSupport = true;
743
744
    // Assume the minimum precisions mandated by the SPIR-V spec.
745
0
    shaderCaps->fFloatIs32Bits = true;
746
0
    shaderCaps->fHalfIs32Bits = false;
747
748
0
    shaderCaps->fMaxFragmentSamplers = std::min(
749
0
                                       std::min(properties.limits.maxPerStageDescriptorSampledImages,
750
0
                                              properties.limits.maxPerStageDescriptorSamplers),
751
0
                                              (uint32_t)INT_MAX);
752
0
}
753
754
bool stencil_format_supported(const skgpu::VulkanInterface* interface,
755
                              VkPhysicalDevice physDev,
756
0
                              VkFormat format) {
757
0
    VkFormatProperties props;
758
0
    memset(&props, 0, sizeof(VkFormatProperties));
759
0
    GR_VK_CALL(interface, GetPhysicalDeviceFormatProperties(physDev, format, &props));
760
0
    return SkToBool(VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT & props.optimalTilingFeatures);
761
0
}
762
763
void GrVkCaps::initStencilFormat(const skgpu::VulkanInterface* interface,
764
0
                                 VkPhysicalDevice physDev) {
765
0
    if (stencil_format_supported(interface, physDev, VK_FORMAT_S8_UINT)) {
766
0
        fPreferredStencilFormat = VK_FORMAT_S8_UINT;
767
0
    } else if (stencil_format_supported(interface, physDev, VK_FORMAT_D24_UNORM_S8_UINT)) {
768
0
        fPreferredStencilFormat = VK_FORMAT_D24_UNORM_S8_UINT;
769
0
    } else {
770
0
        SkASSERT(stencil_format_supported(interface, physDev, VK_FORMAT_D32_SFLOAT_S8_UINT));
771
0
        fPreferredStencilFormat = VK_FORMAT_D32_SFLOAT_S8_UINT;
772
0
    }
773
0
}
Unexecuted instantiation: GrVkCaps::initStencilFormat(skgpu::VulkanInterface const*, VkPhysicalDevice_T*)
Unexecuted instantiation: GrVkCaps::initStencilFormat(skgpu::VulkanInterface const*, VkPhysicalDevice_T*)
774
775
0
static bool format_is_srgb(VkFormat format) {
776
0
    SkASSERT(GrVkFormatIsSupported(format));
777
778
0
    switch (format) {
779
0
        case VK_FORMAT_R8G8B8A8_SRGB:
780
0
            return true;
781
0
        default:
782
0
            return false;
783
0
    }
784
0
}
Unexecuted instantiation: GrVkCaps.cpp:format_is_srgb(VkFormat)
Unexecuted instantiation: GrVkCaps.cpp:format_is_srgb(VkFormat)
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.
788
static constexpr VkFormat kVkFormats[] = {
789
    VK_FORMAT_R8G8B8A8_UNORM,
790
    VK_FORMAT_R8_UNORM,
791
    VK_FORMAT_B8G8R8A8_UNORM,
792
    VK_FORMAT_R5G6B5_UNORM_PACK16,
793
    VK_FORMAT_B5G6R5_UNORM_PACK16,
794
    VK_FORMAT_R16G16B16A16_SFLOAT,
795
    VK_FORMAT_R16_SFLOAT,
796
    VK_FORMAT_R8G8B8_UNORM,
797
    VK_FORMAT_R8G8_UNORM,
798
    VK_FORMAT_A2B10G10R10_UNORM_PACK32,
799
    VK_FORMAT_A2R10G10B10_UNORM_PACK32,
800
    VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
801
    VK_FORMAT_B4G4R4A4_UNORM_PACK16,
802
    VK_FORMAT_R4G4B4A4_UNORM_PACK16,
803
    VK_FORMAT_R8G8B8A8_SRGB,
804
    VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
805
    VK_FORMAT_BC1_RGB_UNORM_BLOCK,
806
    VK_FORMAT_BC1_RGBA_UNORM_BLOCK,
807
    VK_FORMAT_R16_UNORM,
808
    VK_FORMAT_R16G16_UNORM,
809
    VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,
810
    VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
811
    VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16,
812
    VK_FORMAT_R16G16B16A16_UNORM,
813
    VK_FORMAT_R16G16_SFLOAT,
814
};
815
816
0
void GrVkCaps::setColorType(GrColorType colorType, std::initializer_list<VkFormat> formats) {
817
#ifdef SK_DEBUG
818
0
    for (size_t i = 0; i < kNumVkFormats; ++i) {
819
0
        const auto& formatInfo = fFormatTable[i];
820
0
        for (int j = 0; j < formatInfo.fColorTypeInfoCount; ++j) {
821
0
            const auto& ctInfo = formatInfo.fColorTypeInfos[j];
822
0
            if (ctInfo.fColorType == colorType &&
823
0
                !SkToBool(ctInfo.fFlags & ColorTypeInfo::kWrappedOnly_Flag)) {
824
0
                bool found = false;
825
0
                for (auto it = formats.begin(); it != formats.end(); ++it) {
826
0
                    if (kVkFormats[i] == *it) {
827
0
                        found = true;
828
0
                    }
829
0
                }
830
0
                SkASSERT(found);
831
0
            }
832
0
        }
833
0
    }
834
#endif
835
0
    int idx = static_cast<int>(colorType);
836
0
    for (auto it = formats.begin(); it != formats.end(); ++it) {
837
0
        const auto& info = this->getFormatInfo(*it);
838
0
        for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
839
0
            if (info.fColorTypeInfos[i].fColorType == colorType) {
840
0
                fColorTypeToFormatTable[idx] = *it;
841
0
                return;
842
0
            }
843
0
        }
844
0
    }
845
0
}
Unexecuted instantiation: GrVkCaps::setColorType(GrColorType, std::initializer_list<VkFormat>)
Unexecuted instantiation: GrVkCaps::setColorType(GrColorType, std::initializer_list<VkFormat>)
846
847
0
const GrVkCaps::FormatInfo& GrVkCaps::getFormatInfo(VkFormat format) const {
848
0
    GrVkCaps* nonConstThis = const_cast<GrVkCaps*>(this);
849
0
    return nonConstThis->getFormatInfo(format);
850
0
}
851
852
0
GrVkCaps::FormatInfo& GrVkCaps::getFormatInfo(VkFormat format) {
853
0
    static_assert(std::size(kVkFormats) == GrVkCaps::kNumVkFormats,
854
0
                  "Size of VkFormats array must match static value in header");
855
0
    for (size_t i = 0; i < std::size(kVkFormats); ++i) {
856
0
        if (kVkFormats[i] == format) {
857
0
            return fFormatTable[i];
858
0
        }
859
0
    }
860
0
    static FormatInfo kInvalidFormat;
861
0
    return kInvalidFormat;
862
0
}
863
864
void GrVkCaps::initFormatTable(const GrContextOptions& contextOptions,
865
                               const skgpu::VulkanInterface* interface,
866
                               VkPhysicalDevice physDev,
867
                               const VkPhysicalDeviceProperties& properties,
868
                               const VkPhysicalDeviceFeatures2& features,
869
0
                               const skgpu::VulkanExtensions& extensions) {
870
0
    static_assert(std::size(kVkFormats) == GrVkCaps::kNumVkFormats,
871
0
                  "Size of VkFormats array must match static value in header");
872
873
0
    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
0
    {
878
0
        constexpr VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
879
0
        auto& info = this->getFormatInfo(format);
880
0
        info.init(contextOptions, interface, physDev, properties, format);
881
0
        if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
882
0
            info.fColorTypeInfoCount = 2;
883
0
            info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
884
0
            int ctIdx = 0;
885
            // Format: VK_FORMAT_R8G8B8A8_UNORM, Surface: kRGBA_8888
886
0
            {
887
0
                constexpr GrColorType ct = GrColorType::kRGBA_8888;
888
0
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
889
0
                ctInfo.fColorType = ct;
890
0
                ctInfo.fTransferColorType = ct;
891
0
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
892
0
            }
893
            // Format: VK_FORMAT_R8G8B8A8_UNORM, Surface: kRGB_888x
894
0
            {
895
0
                constexpr GrColorType ct = GrColorType::kRGB_888x;
896
0
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
897
0
                ctInfo.fColorType = ct;
898
0
                ctInfo.fTransferColorType = ct;
899
0
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
900
0
                ctInfo.fReadSwizzle = skgpu::Swizzle::RGB1();
901
0
            }
902
0
        }
903
0
    }
904
905
    // Format: VK_FORMAT_R8_UNORM
906
0
    {
907
0
        constexpr VkFormat format = VK_FORMAT_R8_UNORM;
908
0
        auto& info = this->getFormatInfo(format);
909
0
        info.init(contextOptions, interface, physDev, properties, format);
910
0
        if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
911
0
            info.fColorTypeInfoCount = 3;
912
0
            info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
913
0
            int ctIdx = 0;
914
            // Format: VK_FORMAT_R8_UNORM, Surface: kR_8
915
0
            {
916
0
                constexpr GrColorType ct = GrColorType::kR_8;
917
0
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
918
0
                ctInfo.fColorType = ct;
919
0
                ctInfo.fTransferColorType = ct;
920
0
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
921
0
            }
922
            // Format: VK_FORMAT_R8_UNORM, Surface: kAlpha_8
923
0
            {
924
0
                constexpr GrColorType ct = GrColorType::kAlpha_8;
925
0
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
926
0
                ctInfo.fColorType = ct;
927
0
                ctInfo.fTransferColorType = ct;
928
0
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
929
0
                ctInfo.fReadSwizzle = skgpu::Swizzle("000r");
930
0
                ctInfo.fWriteSwizzle = skgpu::Swizzle("a000");
931
0
            }
932
            // Format: VK_FORMAT_R8_UNORM, Surface: kGray_8
933
0
            {
934
0
                constexpr GrColorType ct = GrColorType::kGray_8;
935
0
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
936
0
                ctInfo.fColorType = ct;
937
0
                ctInfo.fTransferColorType = ct;
938
0
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
939
0
                ctInfo.fReadSwizzle = skgpu::Swizzle("rrr1");
940
0
            }
941
0
        }
942
0
    }
943
    // Format: VK_FORMAT_B8G8R8A8_UNORM
944
0
    {
945
0
        constexpr VkFormat format = VK_FORMAT_B8G8R8A8_UNORM;
946
0
        auto& info = this->getFormatInfo(format);
947
0
        info.init(contextOptions, interface, physDev, properties, format);
948
0
        if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
949
0
            info.fColorTypeInfoCount = 2;
950
0
            info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
951
0
            int ctIdx = 0;
952
            // Format: VK_FORMAT_B8G8R8A8_UNORM, Surface: kBGRA_8888
953
0
            {
954
0
                constexpr GrColorType ct = GrColorType::kBGRA_8888;
955
0
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
956
0
                ctInfo.fColorType = ct;
957
0
                ctInfo.fTransferColorType = ct;
958
0
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
959
0
            }
960
            // Format: VK_FORMAT_B8G8R8A8_UNORM, Surface: kRGB_888x
961
            // TODO: add and use kBGR_888X instead
962
0
            {
963
0
                constexpr GrColorType ct = GrColorType::kRGB_888x;
964
0
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
965
0
                ctInfo.fColorType = ct;
966
0
                ctInfo.fTransferColorType = GrColorType::kBGRA_8888;
967
0
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
968
0
                ctInfo.fReadSwizzle = skgpu::Swizzle::RGB1();
969
0
            }
970
0
        }
971
0
    }
972
    // Format: VK_FORMAT_R5G6B5_UNORM_PACK16
973
0
    {
974
0
        constexpr VkFormat format = VK_FORMAT_R5G6B5_UNORM_PACK16;
975
0
        auto& info = this->getFormatInfo(format);
976
0
        info.init(contextOptions, interface, physDev, properties, format);
977
0
        if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
978
0
            info.fColorTypeInfoCount = 1;
979
0
            info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
980
0
            int ctIdx = 0;
981
            // Format: VK_FORMAT_R5G6B5_UNORM_PACK16, Surface: kBGR_565
982
0
            {
983
0
                constexpr GrColorType ct = GrColorType::kBGR_565;
984
0
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
985
0
                ctInfo.fColorType = ct;
986
0
                ctInfo.fTransferColorType = ct;
987
0
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
988
0
            }
989
0
        }
990
0
    }
991
    // Format: VK_FORMAT_B5G6R5_UNORM_PACK16
992
0
    {
993
0
        constexpr VkFormat format = VK_FORMAT_B5G6R5_UNORM_PACK16;
994
0
        auto& info = this->getFormatInfo(format);
995
0
        info.init(contextOptions, interface, physDev, properties, format);
996
0
        if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
997
0
            info.fColorTypeInfoCount = 2;
998
0
            info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
999
0
            int ctIdx = 0;
1000
            // Format: VK_FORMAT_B5G6R5_UNORM_PACK16, Surface: kRGB_565
1001
0
            {
1002
0
                constexpr GrColorType ct = GrColorType::kRGB_565;
1003
0
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1004
0
                ctInfo.fColorType = ct;
1005
0
                ctInfo.fTransferColorType = ct;
1006
0
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
1007
0
            }
1008
            // Format: VK_FORMAT_B5G6R5_UNORM_PACK16, Surface: kBGR_565
1009
            // We need this because there is no kBGR_565_SkColorType.
1010
0
            {
1011
0
                constexpr GrColorType ct = GrColorType::kBGR_565;
1012
0
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1013
0
                ctInfo.fColorType = ct;
1014
0
                ctInfo.fTransferColorType = GrColorType::kRGB_565;
1015
0
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
1016
0
            }
1017
0
        }
1018
0
    }
1019
    // Format: VK_FORMAT_R16G16B16A16_SFLOAT
1020
0
    {
1021
0
        constexpr VkFormat format = VK_FORMAT_R16G16B16A16_SFLOAT;
1022
0
        auto& info = this->getFormatInfo(format);
1023
0
        info.init(contextOptions, interface, physDev, properties, format);
1024
0
        if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1025
0
            info.fColorTypeInfoCount = 2;
1026
0
            info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1027
0
            int ctIdx = 0;
1028
            // Format: VK_FORMAT_R16G16B16A16_SFLOAT, Surface: GrColorType::kRGBA_F16
1029
0
            {
1030
0
                constexpr GrColorType ct = GrColorType::kRGBA_F16;
1031
0
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1032
0
                ctInfo.fColorType = ct;
1033
0
                ctInfo.fTransferColorType = ct;
1034
0
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
1035
0
            }
1036
            // Format: VK_FORMAT_R16G16B16A16_SFLOAT, Surface: GrColorType::kRGBA_F16_Clamped
1037
0
            {
1038
0
                constexpr GrColorType ct = GrColorType::kRGBA_F16_Clamped;
1039
0
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1040
0
                ctInfo.fColorType = ct;
1041
0
                ctInfo.fTransferColorType = ct;
1042
0
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
1043
0
            }
1044
0
        }
1045
0
    }
1046
    // Format: VK_FORMAT_R16_SFLOAT
1047
0
    {
1048
0
        constexpr VkFormat format = VK_FORMAT_R16_SFLOAT;
1049
0
        auto& info = this->getFormatInfo(format);
1050
0
        info.init(contextOptions, interface, physDev, properties, format);
1051
0
        if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1052
0
            info.fColorTypeInfoCount = 1;
1053
0
            info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1054
0
            int ctIdx = 0;
1055
            // Format: VK_FORMAT_R16_SFLOAT, Surface: kAlpha_F16
1056
0
            {
1057
0
                constexpr GrColorType ct = GrColorType::kAlpha_F16;
1058
0
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1059
0
                ctInfo.fColorType = ct;
1060
0
                ctInfo.fTransferColorType = ct;
1061
0
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
1062
0
                ctInfo.fReadSwizzle = skgpu::Swizzle("000r");
1063
0
                ctInfo.fWriteSwizzle = skgpu::Swizzle("a000");
1064
0
            }
1065
0
        }
1066
0
    }
1067
    // Format: VK_FORMAT_R8G8B8_UNORM
1068
0
    {
1069
0
        constexpr VkFormat format = VK_FORMAT_R8G8B8_UNORM;
1070
0
        auto& info = this->getFormatInfo(format);
1071
0
        info.init(contextOptions, interface, physDev, properties, format);
1072
0
        if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1073
0
            info.fColorTypeInfoCount = 1;
1074
0
            info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1075
0
            int ctIdx = 0;
1076
            // Format: VK_FORMAT_R8G8B8_UNORM, Surface: kRGB_888x
1077
0
            {
1078
0
                constexpr GrColorType ct = GrColorType::kRGB_888x;
1079
0
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1080
0
                ctInfo.fColorType = ct;
1081
                // The Vulkan format is 3 bpp so we must convert to/from that when transferring.
1082
0
                ctInfo.fTransferColorType = GrColorType::kRGB_888;
1083
0
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
1084
0
            }
1085
0
        }
1086
0
    }
1087
    // Format: VK_FORMAT_R8G8_UNORM
1088
0
    {
1089
0
        constexpr VkFormat format = VK_FORMAT_R8G8_UNORM;
1090
0
        auto& info = this->getFormatInfo(format);
1091
0
        info.init(contextOptions, interface, physDev, properties, format);
1092
0
        if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1093
0
            info.fColorTypeInfoCount = 1;
1094
0
            info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1095
0
            int ctIdx = 0;
1096
            // Format: VK_FORMAT_R8G8_UNORM, Surface: kRG_88
1097
0
            {
1098
0
                constexpr GrColorType ct = GrColorType::kRG_88;
1099
0
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1100
0
                ctInfo.fColorType = ct;
1101
0
                ctInfo.fTransferColorType = ct;
1102
0
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
1103
0
            }
1104
0
        }
1105
0
    }
1106
    // Format: VK_FORMAT_A2B10G10R10_UNORM_PACK32
1107
0
    {
1108
0
        constexpr VkFormat format = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
1109
0
        auto& info = this->getFormatInfo(format);
1110
0
        info.init(contextOptions, interface, physDev, properties, format);
1111
0
        if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1112
0
            info.fColorTypeInfoCount = 1;
1113
0
            info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1114
0
            int ctIdx = 0;
1115
            // Format: VK_FORMAT_A2B10G10R10_UNORM_PACK32, Surface: kRGBA_1010102
1116
0
            {
1117
0
                constexpr GrColorType ct = GrColorType::kRGBA_1010102;
1118
0
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1119
0
                ctInfo.fColorType = ct;
1120
0
                ctInfo.fTransferColorType = ct;
1121
0
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
1122
0
            }
1123
0
        }
1124
0
    }
1125
    // Format: VK_FORMAT_A2R10G10B10_UNORM_PACK32
1126
0
    {
1127
0
        constexpr VkFormat format = VK_FORMAT_A2R10G10B10_UNORM_PACK32;
1128
0
        auto& info = this->getFormatInfo(format);
1129
0
        info.init(contextOptions, interface, physDev, properties, format);
1130
0
        if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1131
0
            info.fColorTypeInfoCount = 1;
1132
0
            info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1133
0
            int ctIdx = 0;
1134
            // Format: VK_FORMAT_A2R10G10B10_UNORM_PACK32, Surface: kBGRA_1010102
1135
0
            {
1136
0
                constexpr GrColorType ct = GrColorType::kBGRA_1010102;
1137
0
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1138
0
                ctInfo.fColorType = ct;
1139
0
                ctInfo.fTransferColorType = ct;
1140
0
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
1141
0
            }
1142
0
        }
1143
0
    }
1144
1145
0
    bool supportsRGBA10x6 = false;
1146
0
    if (extensions.hasExtension(VK_EXT_RGBA10X6_FORMATS_EXTENSION_NAME, 1)) {
1147
0
        auto rgba10x6Feature =
1148
0
                skgpu::GetExtensionFeatureStruct<VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT>(
1149
0
                        features, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RGBA10X6_FORMATS_FEATURES_EXT);
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
0
        supportsRGBA10x6 = rgba10x6Feature  && rgba10x6Feature->formatRgba10x6WithoutYCbCrSampler;
1154
0
    }
1155
1156
    // Format: VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16
1157
0
    if (supportsRGBA10x6) {
1158
0
        constexpr VkFormat format = VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16;
1159
0
        auto& info = this->getFormatInfo(format);
1160
0
        info.init(contextOptions, interface, physDev, properties, format);
1161
0
        if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1162
0
            info.fColorTypeInfoCount = 1;
1163
0
            info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1164
0
            int ctIdx = 0;
1165
            // Format: VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16, Surface: kRGBA_10x6
1166
0
            {
1167
0
                constexpr GrColorType ct = GrColorType::kRGBA_10x6;
1168
0
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1169
0
                ctInfo.fColorType = ct;
1170
0
                ctInfo.fTransferColorType = ct;
1171
0
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
1172
0
            }
1173
0
        }
1174
0
    }
1175
1176
    // Format: VK_FORMAT_B4G4R4A4_UNORM_PACK16
1177
0
    {
1178
0
        constexpr VkFormat format = VK_FORMAT_B4G4R4A4_UNORM_PACK16;
1179
0
        auto& info = this->getFormatInfo(format);
1180
0
        info.init(contextOptions, interface, physDev, properties, format);
1181
0
        if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1182
0
            info.fColorTypeInfoCount = 1;
1183
0
            info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1184
0
            int ctIdx = 0;
1185
            // Format: VK_FORMAT_B4G4R4A4_UNORM_PACK16, Surface: kABGR_4444
1186
0
            {
1187
0
                constexpr GrColorType ct = GrColorType::kABGR_4444;
1188
0
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1189
0
                ctInfo.fColorType = ct;
1190
0
                ctInfo.fTransferColorType = ct;
1191
0
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
1192
0
                ctInfo.fReadSwizzle = skgpu::Swizzle::BGRA();
1193
0
                ctInfo.fWriteSwizzle = skgpu::Swizzle::BGRA();
1194
0
            }
1195
0
        }
1196
0
    }
1197
1198
    // Format: VK_FORMAT_R4G4B4A4_UNORM_PACK16
1199
0
    {
1200
0
        constexpr VkFormat format = VK_FORMAT_R4G4B4A4_UNORM_PACK16;
1201
0
        auto& info = this->getFormatInfo(format);
1202
0
        info.init(contextOptions, interface, physDev, properties, format);
1203
0
        if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1204
0
            info.fColorTypeInfoCount = 1;
1205
0
            info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1206
0
            int ctIdx = 0;
1207
            // Format: VK_FORMAT_R4G4B4A4_UNORM_PACK16, Surface: kABGR_4444
1208
0
            {
1209
0
                constexpr GrColorType ct = GrColorType::kABGR_4444;
1210
0
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1211
0
                ctInfo.fColorType = ct;
1212
0
                ctInfo.fTransferColorType = ct;
1213
0
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
1214
0
            }
1215
0
        }
1216
0
    }
1217
    // Format: VK_FORMAT_R8G8B8A8_SRGB
1218
0
    {
1219
0
        constexpr VkFormat format = VK_FORMAT_R8G8B8A8_SRGB;
1220
0
        auto& info = this->getFormatInfo(format);
1221
0
        info.init(contextOptions, interface, physDev, properties, format);
1222
0
        if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1223
0
            info.fColorTypeInfoCount = 1;
1224
0
            info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1225
0
            int ctIdx = 0;
1226
            // Format: VK_FORMAT_R8G8B8A8_SRGB, Surface: kRGBA_8888_SRGB
1227
0
            {
1228
0
                constexpr GrColorType ct = GrColorType::kRGBA_8888_SRGB;
1229
0
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1230
0
                ctInfo.fColorType = ct;
1231
0
                ctInfo.fTransferColorType = ct;
1232
0
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
1233
0
            }
1234
0
        }
1235
0
    }
1236
    // Format: VK_FORMAT_R16_UNORM
1237
0
    {
1238
0
        constexpr VkFormat format = VK_FORMAT_R16_UNORM;
1239
0
        auto& info = this->getFormatInfo(format);
1240
0
        info.init(contextOptions, interface, physDev, properties, format);
1241
0
        if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1242
0
            info.fColorTypeInfoCount = 1;
1243
0
            info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1244
0
            int ctIdx = 0;
1245
            // Format: VK_FORMAT_R16_UNORM, Surface: kAlpha_16
1246
0
            {
1247
0
                constexpr GrColorType ct = GrColorType::kAlpha_16;
1248
0
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1249
0
                ctInfo.fColorType = ct;
1250
0
                ctInfo.fTransferColorType = ct;
1251
0
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
1252
0
                ctInfo.fReadSwizzle = skgpu::Swizzle("000r");
1253
0
                ctInfo.fWriteSwizzle = skgpu::Swizzle("a000");
1254
0
            }
1255
0
        }
1256
0
    }
1257
    // Format: VK_FORMAT_R16G16_UNORM
1258
0
    {
1259
0
        constexpr VkFormat format = VK_FORMAT_R16G16_UNORM;
1260
0
        auto& info = this->getFormatInfo(format);
1261
0
        info.init(contextOptions, interface, physDev, properties, format);
1262
0
        if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1263
0
            info.fColorTypeInfoCount = 1;
1264
0
            info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1265
0
            int ctIdx = 0;
1266
            // Format: VK_FORMAT_R16G16_UNORM, Surface: kRG_1616
1267
0
            {
1268
0
                constexpr GrColorType ct = GrColorType::kRG_1616;
1269
0
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1270
0
                ctInfo.fColorType = ct;
1271
0
                ctInfo.fTransferColorType = ct;
1272
0
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
1273
0
            }
1274
0
        }
1275
0
    }
1276
    // Format: VK_FORMAT_R16G16B16A16_UNORM
1277
0
    {
1278
0
        constexpr VkFormat format = VK_FORMAT_R16G16B16A16_UNORM;
1279
0
        auto& info = this->getFormatInfo(format);
1280
0
        info.init(contextOptions, interface, physDev, properties, format);
1281
0
        if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1282
0
            info.fColorTypeInfoCount = 1;
1283
0
            info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1284
0
            int ctIdx = 0;
1285
            // Format: VK_FORMAT_R16G16B16A16_UNORM, Surface: kRGBA_16161616
1286
0
            {
1287
0
                constexpr GrColorType ct = GrColorType::kRGBA_16161616;
1288
0
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1289
0
                ctInfo.fColorType = ct;
1290
0
                ctInfo.fTransferColorType = ct;
1291
0
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
1292
0
            }
1293
0
        }
1294
0
    }
1295
    // Format: VK_FORMAT_R16G16_SFLOAT
1296
0
    {
1297
0
        constexpr VkFormat format = VK_FORMAT_R16G16_SFLOAT;
1298
0
        auto& info = this->getFormatInfo(format);
1299
0
        info.init(contextOptions, interface, physDev, properties, format);
1300
0
        if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1301
0
            info.fColorTypeInfoCount = 1;
1302
0
            info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1303
0
            int ctIdx = 0;
1304
            // Format: VK_FORMAT_R16G16_SFLOAT, Surface: kRG_F16
1305
0
            {
1306
0
                constexpr GrColorType ct = GrColorType::kRG_F16;
1307
0
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1308
0
                ctInfo.fColorType = ct;
1309
0
                ctInfo.fTransferColorType = ct;
1310
0
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
1311
0
            }
1312
0
        }
1313
0
    }
1314
    // Format: VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM
1315
0
    {
1316
0
        constexpr VkFormat format = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM;
1317
0
        auto& info = this->getFormatInfo(format);
1318
0
        if (fSupportsYcbcrConversion) {
1319
0
            info.init(contextOptions, interface, physDev, properties, format);
1320
0
        }
1321
0
        if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1322
0
            info.fColorTypeInfoCount = 1;
1323
0
            info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1324
0
            int ctIdx = 0;
1325
            // Format: VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, Surface: kRGB_888x
1326
0
            {
1327
0
                constexpr GrColorType ct = GrColorType::kRGB_888x;
1328
0
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1329
0
                ctInfo.fColorType = ct;
1330
0
                ctInfo.fTransferColorType = ct;
1331
0
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kWrappedOnly_Flag;
1332
0
            }
1333
0
        }
1334
0
    }
1335
    // Format: VK_FORMAT_G8_B8R8_2PLANE_420_UNORM
1336
0
    {
1337
0
        constexpr VkFormat format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
1338
0
        auto& info = this->getFormatInfo(format);
1339
0
        if (fSupportsYcbcrConversion) {
1340
0
            info.init(contextOptions, interface, physDev, properties, format);
1341
0
        }
1342
0
        if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1343
0
            info.fColorTypeInfoCount = 1;
1344
0
            info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1345
0
            int ctIdx = 0;
1346
            // Format: VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, Surface: kRGB_888x
1347
0
            {
1348
0
                constexpr GrColorType ct = GrColorType::kRGB_888x;
1349
0
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1350
0
                ctInfo.fColorType = ct;
1351
0
                ctInfo.fTransferColorType = ct;
1352
0
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kWrappedOnly_Flag;
1353
0
            }
1354
0
        }
1355
0
    }
1356
    // Format: VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16
1357
0
    {
1358
0
        constexpr VkFormat format = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16;
1359
0
        auto& info = this->getFormatInfo(format);
1360
0
        if (fSupportsYcbcrConversion) {
1361
0
            info.init(contextOptions, interface, physDev, properties, format);
1362
0
        }
1363
0
        if (SkToBool(info.fOptimalFlags & FormatInfo::kTexturable_Flag)) {
1364
0
            info.fColorTypeInfoCount = 1;
1365
0
            info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount);
1366
0
            int ctIdx = 0;
1367
            // Format: VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, Surface: kRGBA_1010102
1368
0
            {
1369
0
                constexpr GrColorType ct = GrColorType::kRGBA_1010102;
1370
0
                auto& ctInfo = info.fColorTypeInfos[ctIdx++];
1371
0
                ctInfo.fColorType = ct;
1372
0
                ctInfo.fTransferColorType = ct;
1373
0
                ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kWrappedOnly_Flag;
1374
0
            }
1375
0
        }
1376
0
    }
1377
    // Format: VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK
1378
0
    {
1379
0
        constexpr VkFormat format = VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
1380
0
        auto& info = this->getFormatInfo(format);
1381
0
        info.init(contextOptions, interface, physDev, properties, format);
1382
        // Setting this to texel block size
1383
        // No supported GrColorTypes.
1384
0
    }
1385
1386
    // Format: VK_FORMAT_BC1_RGB_UNORM_BLOCK
1387
0
    {
1388
0
        constexpr VkFormat format = VK_FORMAT_BC1_RGB_UNORM_BLOCK;
1389
0
        auto& info = this->getFormatInfo(format);
1390
0
        info.init(contextOptions, interface, physDev, properties, format);
1391
        // Setting this to texel block size
1392
        // No supported GrColorTypes.
1393
0
    }
1394
1395
    // Format: VK_FORMAT_BC1_RGBA_UNORM_BLOCK
1396
0
    {
1397
0
        constexpr VkFormat format = VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
1398
0
        auto& info = this->getFormatInfo(format);
1399
0
        info.init(contextOptions, interface, physDev, properties, format);
1400
        // Setting this to texel block size
1401
        // No supported GrColorTypes.
1402
0
    }
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
0
    this->setColorType(GrColorType::kAlpha_8,          { VK_FORMAT_R8_UNORM });
1410
0
    this->setColorType(GrColorType::kBGR_565,          { VK_FORMAT_R5G6B5_UNORM_PACK16,
1411
0
                                                         VK_FORMAT_B5G6R5_UNORM_PACK16 });
1412
0
    this->setColorType(GrColorType::kRGB_565,          { VK_FORMAT_B5G6R5_UNORM_PACK16 });
1413
0
    this->setColorType(GrColorType::kABGR_4444,        { VK_FORMAT_R4G4B4A4_UNORM_PACK16,
1414
0
                                                         VK_FORMAT_B4G4R4A4_UNORM_PACK16 });
1415
0
    this->setColorType(GrColorType::kRGBA_8888,        { VK_FORMAT_R8G8B8A8_UNORM });
1416
0
    this->setColorType(GrColorType::kRGBA_8888_SRGB,   { VK_FORMAT_R8G8B8A8_SRGB });
1417
0
    this->setColorType(GrColorType::kRGB_888x,         { VK_FORMAT_R8G8B8_UNORM,
1418
0
                                                         VK_FORMAT_R8G8B8A8_UNORM,
1419
0
                                                         VK_FORMAT_B8G8R8A8_UNORM, });
1420
0
    this->setColorType(GrColorType::kRG_88,            { VK_FORMAT_R8G8_UNORM });
1421
0
    this->setColorType(GrColorType::kBGRA_8888,        { VK_FORMAT_B8G8R8A8_UNORM });
1422
0
    this->setColorType(GrColorType::kRGBA_1010102,     { VK_FORMAT_A2B10G10R10_UNORM_PACK32 });
1423
0
    this->setColorType(GrColorType::kBGRA_1010102,     { VK_FORMAT_A2R10G10B10_UNORM_PACK32 });
1424
0
    this->setColorType(GrColorType::kGray_8,           { VK_FORMAT_R8_UNORM });
1425
0
    this->setColorType(GrColorType::kAlpha_F16,        { VK_FORMAT_R16_SFLOAT });
1426
0
    this->setColorType(GrColorType::kRGBA_F16,         { VK_FORMAT_R16G16B16A16_SFLOAT });
1427
0
    this->setColorType(GrColorType::kRGBA_F16_Clamped, { VK_FORMAT_R16G16B16A16_SFLOAT });
1428
0
    this->setColorType(GrColorType::kAlpha_16,         { VK_FORMAT_R16_UNORM });
1429
0
    this->setColorType(GrColorType::kRG_1616,          { VK_FORMAT_R16G16_UNORM });
1430
0
    this->setColorType(GrColorType::kRGBA_16161616,    { VK_FORMAT_R16G16B16A16_UNORM });
1431
0
    this->setColorType(GrColorType::kRG_F16,           { VK_FORMAT_R16G16_SFLOAT });
1432
0
}
1433
1434
0
void GrVkCaps::FormatInfo::InitFormatFlags(VkFormatFeatureFlags vkFlags, uint16_t* flags) {
1435
0
    if (SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT & vkFlags) &&
1436
0
        SkToBool(VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT & vkFlags)) {
1437
0
        *flags = *flags | kTexturable_Flag;
1438
1439
        // Ganesh assumes that all renderable surfaces are also texturable
1440
0
        if (SkToBool(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT & vkFlags)) {
1441
0
            *flags = *flags | kRenderable_Flag;
1442
0
        }
1443
0
    }
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
1448
0
    if (SkToBool(VK_FORMAT_FEATURE_BLIT_SRC_BIT & vkFlags)) {
1449
0
        *flags = *flags | kBlitSrc_Flag;
1450
0
    }
1451
1452
0
    if (SkToBool(VK_FORMAT_FEATURE_BLIT_DST_BIT & vkFlags)) {
1453
0
        *flags = *flags | kBlitDst_Flag;
1454
0
    }
1455
0
}
1456
1457
void GrVkCaps::FormatInfo::initSampleCounts(const GrContextOptions& contextOptions,
1458
                                            const skgpu::VulkanInterface* interface,
1459
                                            VkPhysicalDevice physDev,
1460
                                            const VkPhysicalDeviceProperties& physProps,
1461
0
                                            VkFormat format) {
1462
0
    VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
1463
0
                              VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1464
0
                              VK_IMAGE_USAGE_SAMPLED_BIT |
1465
0
                              VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1466
0
    VkImageFormatProperties properties;
1467
0
    GR_VK_CALL(interface, GetPhysicalDeviceImageFormatProperties(physDev,
1468
0
                                                                 format,
1469
0
                                                                 VK_IMAGE_TYPE_2D,
1470
0
                                                                 VK_IMAGE_TILING_OPTIMAL,
1471
0
                                                                 usage,
1472
0
                                                                 0,  // createFlags
1473
0
                                                                 &properties));
1474
0
    VkSampleCountFlags flags = properties.sampleCounts;
1475
0
    if (flags & VK_SAMPLE_COUNT_1_BIT) {
1476
0
        fColorSampleCounts.push_back(1);
1477
0
    }
1478
0
    if (kImagination_VkVendor == physProps.vendorID) {
1479
        // MSAA does not work on imagination
1480
0
        return;
1481
0
    }
1482
0
    if (kIntel_VkVendor == physProps.vendorID) {
1483
0
        if (GetIntelGen(GetIntelGPUType(physProps.deviceID)) < 12 ||
1484
0
            !contextOptions.fAllowMSAAOnNewIntel) {
1485
            // MSAA doesn't work well on Intel GPUs chromium:527565, chromium:983926
1486
0
            return;
1487
0
        }
1488
0
    }
1489
0
    if (flags & VK_SAMPLE_COUNT_2_BIT) {
1490
0
        fColorSampleCounts.push_back(2);
1491
0
    }
1492
0
    if (flags & VK_SAMPLE_COUNT_4_BIT) {
1493
0
        fColorSampleCounts.push_back(4);
1494
0
    }
1495
0
    if (flags & VK_SAMPLE_COUNT_8_BIT) {
1496
0
        fColorSampleCounts.push_back(8);
1497
0
    }
1498
0
    if (flags & VK_SAMPLE_COUNT_16_BIT) {
1499
0
        fColorSampleCounts.push_back(16);
1500
0
    }
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
0
}
1504
1505
void GrVkCaps::FormatInfo::init(const GrContextOptions& contextOptions,
1506
                                const skgpu::VulkanInterface* interface,
1507
                                VkPhysicalDevice physDev,
1508
                                const VkPhysicalDeviceProperties& properties,
1509
0
                                VkFormat format) {
1510
0
    VkFormatProperties props;
1511
0
    memset(&props, 0, sizeof(VkFormatProperties));
1512
0
    GR_VK_CALL(interface, GetPhysicalDeviceFormatProperties(physDev, format, &props));
1513
0
    InitFormatFlags(props.linearTilingFeatures, &fLinearFlags);
1514
0
    InitFormatFlags(props.optimalTilingFeatures, &fOptimalFlags);
1515
0
    if (fOptimalFlags & kRenderable_Flag) {
1516
0
        this->initSampleCounts(contextOptions, interface, physDev, properties, format);
1517
0
    }
1518
0
}
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.
1523
0
static bool backend_format_is_external(const GrBackendFormat& format) {
1524
0
    const GrVkYcbcrConversionInfo* ycbcrInfo = GrBackendFormats::GetVkYcbcrConversionInfo(format);
1525
0
    SkASSERT(ycbcrInfo);
1526
1527
    // All external formats have a valid ycbcrInfo used for sampling and a non zero external format.
1528
0
    if (ycbcrInfo->isValid() && ycbcrInfo->fExternalFormat != 0) {
1529
#ifdef SK_DEBUG
1530
        VkFormat vkFormat;
1531
0
        SkAssertResult(GrBackendFormats::AsVkFormat(format, &vkFormat));
1532
0
        SkASSERT(vkFormat == VK_FORMAT_UNDEFINED);
1533
#endif
1534
0
        return true;
1535
0
    }
1536
0
    return false;
1537
0
}
Unexecuted instantiation: GrVkCaps.cpp:backend_format_is_external(GrBackendFormat const&)
Unexecuted instantiation: GrVkCaps.cpp:backend_format_is_external(GrBackendFormat const&)
1538
1539
0
bool GrVkCaps::isFormatSRGB(const GrBackendFormat& format) const {
1540
0
    VkFormat vkFormat;
1541
0
    if (!GrBackendFormats::AsVkFormat(format, &vkFormat)) {
1542
0
        return false;
1543
0
    }
1544
0
    if (backend_format_is_external(format)) {
1545
0
        return false;
1546
0
    }
1547
1548
0
    return format_is_srgb(vkFormat);
1549
0
}
1550
1551
0
bool GrVkCaps::isFormatTexturable(const GrBackendFormat& format, GrTextureType) const {
1552
0
    VkFormat vkFormat;
1553
0
    if (!GrBackendFormats::AsVkFormat(format, &vkFormat)) {
1554
0
        return false;
1555
0
    }
1556
0
    if (backend_format_is_external(format)) {
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
0
        return true;
1560
0
    }
1561
0
    return this->isVkFormatTexturable(vkFormat);
1562
0
}
1563
1564
0
bool GrVkCaps::isVkFormatTexturable(VkFormat format) const {
1565
0
    const FormatInfo& info = this->getFormatInfo(format);
1566
0
    return SkToBool(FormatInfo::kTexturable_Flag & info.fOptimalFlags);
1567
0
}
1568
1569
bool GrVkCaps::isFormatAsColorTypeRenderable(GrColorType ct, const GrBackendFormat& format,
1570
0
                                             int sampleCount) const {
1571
0
    if (!this->isFormatRenderable(format, sampleCount)) {
1572
0
        return false;
1573
0
    }
1574
0
    VkFormat vkFormat;
1575
0
    if (!GrBackendFormats::AsVkFormat(format, &vkFormat)) {
1576
0
        return false;
1577
0
    }
1578
0
    const auto& info = this->getFormatInfo(vkFormat);
1579
0
    if (!SkToBool(info.colorTypeFlags(ct) & ColorTypeInfo::kRenderable_Flag)) {
1580
0
        return false;
1581
0
    }
1582
0
    return true;
1583
0
}
1584
1585
0
bool GrVkCaps::isFormatRenderable(const GrBackendFormat& format, int sampleCount) const {
1586
0
    VkFormat vkFormat;
1587
0
    if (!GrBackendFormats::AsVkFormat(format, &vkFormat)) {
1588
0
        return false;
1589
0
    }
1590
0
    return this->isFormatRenderable(vkFormat, sampleCount);
1591
0
}
1592
1593
0
bool GrVkCaps::isFormatRenderable(VkFormat format, int sampleCount) const {
1594
0
    return sampleCount <= this->maxRenderTargetSampleCount(format);
1595
0
}
1596
1597
int GrVkCaps::getRenderTargetSampleCount(int requestedCount,
1598
0
                                         const GrBackendFormat& format) const {
1599
0
    VkFormat vkFormat;
1600
0
    if (!GrBackendFormats::AsVkFormat(format, &vkFormat)) {
1601
0
        return 0;
1602
0
    }
1603
1604
0
    return this->getRenderTargetSampleCount(requestedCount, vkFormat);
1605
0
}
1606
1607
0
int GrVkCaps::getRenderTargetSampleCount(int requestedCount, VkFormat format) const {
1608
0
    requestedCount = std::max(1, requestedCount);
1609
1610
0
    const FormatInfo& info = this->getFormatInfo(format);
1611
1612
0
    int count = info.fColorSampleCounts.size();
1613
1614
0
    if (!count) {
1615
0
        return 0;
1616
0
    }
1617
1618
0
    if (1 == requestedCount) {
1619
0
        SkASSERT(!info.fColorSampleCounts.empty() && info.fColorSampleCounts[0] == 1);
1620
0
        return 1;
1621
0
    }
1622
1623
0
    for (int i = 0; i < count; ++i) {
1624
0
        if (info.fColorSampleCounts[i] >= requestedCount) {
1625
0
            return info.fColorSampleCounts[i];
1626
0
        }
1627
0
    }
1628
0
    return 0;
1629
0
}
Unexecuted instantiation: GrVkCaps::getRenderTargetSampleCount(int, VkFormat) const
Unexecuted instantiation: GrVkCaps::getRenderTargetSampleCount(int, VkFormat) const
1630
1631
0
int GrVkCaps::maxRenderTargetSampleCount(const GrBackendFormat& format) const {
1632
0
    VkFormat vkFormat;
1633
0
    if (!GrBackendFormats::AsVkFormat(format, &vkFormat)) {
1634
0
        return 0;
1635
0
    }
1636
0
    return this->maxRenderTargetSampleCount(vkFormat);
1637
0
}
1638
1639
0
int GrVkCaps::maxRenderTargetSampleCount(VkFormat format) const {
1640
0
    const FormatInfo& info = this->getFormatInfo(format);
1641
1642
0
    const auto& table = info.fColorSampleCounts;
1643
0
    if (table.empty()) {
1644
0
        return 0;
1645
0
    }
1646
0
    return table[table.size() - 1];
1647
0
}
1648
1649
0
static inline size_t align_to_4(size_t v) {
1650
0
    switch (v & 0b11) {
1651
        // v is already a multiple of 4.
1652
0
        case 0:     return v;
1653
        // v is a multiple of 2 but not 4.
1654
0
        case 2:     return 2 * v;
1655
        // v is not a multiple of 2.
1656
0
        default:    return 4 * v;
1657
0
    }
1658
0
}
1659
1660
GrCaps::SupportedWrite GrVkCaps::supportedWritePixelsColorType(GrColorType surfaceColorType,
1661
                                                               const GrBackendFormat& surfaceFormat,
1662
0
                                                               GrColorType srcColorType) const {
1663
0
    VkFormat vkFormat;
1664
0
    if (!GrBackendFormats::AsVkFormat(surfaceFormat, &vkFormat)) {
1665
0
        return {GrColorType::kUnknown, 0};
1666
0
    }
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
0
    if (backend_format_is_external(surfaceFormat) || skgpu::VkFormatNeedsYcbcrSampler(vkFormat)) {
1671
0
        return {GrColorType::kUnknown, 0};
1672
0
    }
1673
1674
    // The VkBufferImageCopy bufferOffset field must be both a multiple of 4 and of a single texel.
1675
0
    size_t offsetAlignment = align_to_4(skgpu::VkFormatBytesPerBlock(vkFormat));
1676
1677
0
    const auto& info = this->getFormatInfo(vkFormat);
1678
0
    for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1679
0
        const auto& ctInfo = info.fColorTypeInfos[i];
1680
0
        if (ctInfo.fColorType == surfaceColorType) {
1681
0
            return {ctInfo.fTransferColorType, offsetAlignment};
1682
0
        }
1683
0
    }
1684
0
    return {GrColorType::kUnknown, 0};
1685
0
}
1686
1687
GrCaps::SurfaceReadPixelsSupport GrVkCaps::surfaceSupportsReadPixels(
1688
0
        const GrSurface* surface) const {
1689
0
    if (surface->isProtected()) {
1690
0
        return SurfaceReadPixelsSupport::kUnsupported;
1691
0
    }
1692
0
    if (auto tex = static_cast<const GrVkTexture*>(surface->asTexture())) {
1693
0
        auto texImage = tex->textureImage();
1694
0
        if (!texImage) {
1695
0
            return SurfaceReadPixelsSupport::kUnsupported;
1696
0
        }
1697
        // We can't directly read from a VkImage that has a ycbcr sampler.
1698
0
        if (texImage->ycbcrConversionInfo().isValid()) {
1699
0
            return SurfaceReadPixelsSupport::kCopyToTexture2D;
1700
0
        }
1701
        // We can't directly read from a compressed format
1702
0
        if (skgpu::VkFormatIsCompressed(texImage->imageFormat())) {
1703
0
            return SurfaceReadPixelsSupport::kCopyToTexture2D;
1704
0
        }
1705
0
        return SurfaceReadPixelsSupport::kSupported;
1706
0
    } else if (auto rt = surface->asRenderTarget()) {
1707
0
        if (rt->numSamples() > 1) {
1708
0
            return SurfaceReadPixelsSupport::kCopyToTexture2D;
1709
0
        }
1710
0
        return SurfaceReadPixelsSupport::kSupported;
1711
0
    }
1712
0
    return SurfaceReadPixelsSupport::kUnsupported;
1713
0
}
1714
1715
0
GrColorType GrVkCaps::transferColorType(VkFormat vkFormat, GrColorType surfaceColorType) const {
1716
0
    const auto& info = this->getFormatInfo(vkFormat);
1717
0
    for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1718
0
        if (info.fColorTypeInfos[i].fColorType == surfaceColorType) {
1719
0
            return info.fColorTypeInfos[i].fTransferColorType;
1720
0
        }
1721
0
    }
1722
0
    return GrColorType::kUnknown;
1723
0
}
1724
1725
0
bool GrVkCaps::onSurfaceSupportsWritePixels(const GrSurface* surface) const {
1726
0
    if (auto rt = surface->asRenderTarget()) {
1727
0
        return rt->numSamples() <= 1 && SkToBool(surface->asTexture());
1728
0
    }
1729
    // We can't write to a texture that has a ycbcr sampler.
1730
0
    if (auto tex = static_cast<const GrVkTexture*>(surface->asTexture())) {
1731
0
        auto texImage = tex->textureImage();
1732
0
        if (!texImage) {
1733
0
            return false;
1734
0
        }
1735
        // We can't directly read from a VkImage that has a ycbcr sampler.
1736
0
        if (texImage->ycbcrConversionInfo().isValid()) {
1737
0
            return false;
1738
0
        }
1739
0
    }
1740
0
    return true;
1741
0
}
1742
1743
bool GrVkCaps::onAreColorTypeAndFormatCompatible(GrColorType ct,
1744
0
                                                 const GrBackendFormat& format) const {
1745
0
    VkFormat vkFormat;
1746
0
    if (!GrBackendFormats::AsVkFormat(format, &vkFormat)) {
1747
0
        return false;
1748
0
    }
1749
0
    const GrVkYcbcrConversionInfo* ycbcrInfo = GrBackendFormats::GetVkYcbcrConversionInfo(format);
1750
0
    SkASSERT(ycbcrInfo);
1751
1752
0
    if (ycbcrInfo->isValid() && !skgpu::VkFormatNeedsYcbcrSampler(vkFormat)) {
1753
        // Format may be undefined for external images, which are required to have YCbCr conversion.
1754
0
        if (VK_FORMAT_UNDEFINED == vkFormat && ycbcrInfo->fExternalFormat != 0) {
1755
0
            return true;
1756
0
        }
1757
0
        return false;
1758
0
    }
1759
1760
0
    const auto& info = this->getFormatInfo(vkFormat);
1761
0
    for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1762
0
        if (info.fColorTypeInfos[i].fColorType == ct) {
1763
0
            return true;
1764
0
        }
1765
0
    }
1766
0
    return false;
1767
0
}
Unexecuted instantiation: GrVkCaps::onAreColorTypeAndFormatCompatible(GrColorType, GrBackendFormat const&) const
Unexecuted instantiation: GrVkCaps::onAreColorTypeAndFormatCompatible(GrColorType, GrBackendFormat const&) const
1768
1769
0
GrBackendFormat GrVkCaps::onGetDefaultBackendFormat(GrColorType ct) const {
1770
0
    VkFormat format = this->getFormatFromColorType(ct);
1771
0
    if (format == VK_FORMAT_UNDEFINED) {
1772
0
        return {};
1773
0
    }
1774
0
    return GrBackendFormats::MakeVk(format);
1775
0
}
1776
1777
0
bool GrVkCaps::onSupportsDynamicMSAA(const GrRenderTargetProxy* rtProxy) const {
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
0
    return this->supportsDiscardableMSAAForDMSAA() &&
1782
0
           rtProxy->supportsVkInputAttachment() &&
1783
0
           rtProxy->numSamples() == 1;
1784
0
}
1785
1786
0
bool GrVkCaps::renderTargetSupportsDiscardableMSAA(const GrVkRenderTarget* rt) const {
1787
0
    return rt->resolveAttachment() &&
1788
0
           rt->resolveAttachment()->supportsInputAttachmentUsage() &&
1789
0
           ((rt->numSamples() > 1 && this->preferDiscardableMSAAAttachment()) ||
1790
0
            (rt->numSamples() == 1 && this->supportsDiscardableMSAAForDMSAA()));
1791
0
}
1792
1793
0
bool GrVkCaps::programInfoWillUseDiscardableMSAA(const GrProgramInfo& programInfo) const {
1794
0
    return programInfo.targetHasVkResolveAttachmentWithInput() &&
1795
0
           programInfo.numSamples() > 1 &&
1796
0
           ((programInfo.targetsNumSamples() > 1 && this->preferDiscardableMSAAAttachment()) ||
1797
0
            (programInfo.targetsNumSamples() == 1 && this->supportsDiscardableMSAAForDMSAA()));
1798
0
}
1799
1800
GrBackendFormat GrVkCaps::getBackendFormatFromCompressionType(
1801
0
        SkTextureCompressionType compressionType) const {
1802
0
    switch (compressionType) {
1803
0
        case SkTextureCompressionType::kNone:
1804
0
            return {};
1805
0
        case SkTextureCompressionType::kETC2_RGB8_UNORM:
1806
0
            if (this->isVkFormatTexturable(VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK)) {
1807
0
                return GrBackendFormats::MakeVk(VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK);
1808
0
            }
1809
0
            return {};
1810
0
        case SkTextureCompressionType::kBC1_RGB8_UNORM:
1811
0
            if (this->isVkFormatTexturable(VK_FORMAT_BC1_RGB_UNORM_BLOCK)) {
1812
0
                return GrBackendFormats::MakeVk(VK_FORMAT_BC1_RGB_UNORM_BLOCK);
1813
0
            }
1814
0
            return {};
1815
0
        case SkTextureCompressionType::kBC1_RGBA8_UNORM:
1816
0
            if (this->isVkFormatTexturable(VK_FORMAT_BC1_RGBA_UNORM_BLOCK)) {
1817
0
                return GrBackendFormats::MakeVk(VK_FORMAT_BC1_RGBA_UNORM_BLOCK);
1818
0
            }
1819
0
            return {};
1820
0
    }
1821
1822
0
    SkUNREACHABLE;
1823
0
}
1824
1825
skgpu::Swizzle GrVkCaps::onGetReadSwizzle(const GrBackendFormat& format,
1826
0
                                          GrColorType colorType) const {
1827
0
    VkFormat vkFormat;
1828
0
    SkAssertResult(GrBackendFormats::AsVkFormat(format, &vkFormat));
1829
0
    const GrVkYcbcrConversionInfo* ycbcrInfo = GrBackendFormats::GetVkYcbcrConversionInfo(format);
1830
0
    SkASSERT(ycbcrInfo);
1831
0
    if (ycbcrInfo->isValid() && ycbcrInfo->fExternalFormat != 0) {
1832
        // We allow these to work with any color type and never swizzle. See
1833
        // onAreColorTypeAndFormatCompatible.
1834
0
        return skgpu::Swizzle{"rgba"};
1835
0
    }
1836
1837
0
    const auto& info = this->getFormatInfo(vkFormat);
1838
0
    for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1839
0
        const auto& ctInfo = info.fColorTypeInfos[i];
1840
0
        if (ctInfo.fColorType == colorType) {
1841
0
            return ctInfo.fReadSwizzle;
1842
0
        }
1843
0
    }
1844
0
    SkDEBUGFAILF("Illegal color type (%d) and format (%d) combination.",
1845
0
                 (int)colorType, (int)vkFormat);
1846
0
    return {};
1847
0
}
Unexecuted instantiation: GrVkCaps::onGetReadSwizzle(GrBackendFormat const&, GrColorType) const
Unexecuted instantiation: GrVkCaps::onGetReadSwizzle(GrBackendFormat const&, GrColorType) const
1848
1849
skgpu::Swizzle GrVkCaps::getWriteSwizzle(const GrBackendFormat& format,
1850
0
                                         GrColorType colorType) const {
1851
0
    VkFormat vkFormat;
1852
0
    SkAssertResult(GrBackendFormats::AsVkFormat(format, &vkFormat));
1853
0
    const auto& info = this->getFormatInfo(vkFormat);
1854
0
    for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1855
0
        const auto& ctInfo = info.fColorTypeInfos[i];
1856
0
        if (ctInfo.fColorType == colorType) {
1857
0
            return ctInfo.fWriteSwizzle;
1858
0
        }
1859
0
    }
1860
0
    SkDEBUGFAILF("Illegal color type (%d) and format (%d) combination.",
1861
0
                 (int)colorType, (int)vkFormat);
1862
0
    return {};
1863
0
}
Unexecuted instantiation: GrVkCaps::getWriteSwizzle(GrBackendFormat const&, GrColorType) const
Unexecuted instantiation: GrVkCaps::getWriteSwizzle(GrBackendFormat const&, GrColorType) const
1864
1865
0
GrDstSampleFlags GrVkCaps::onGetDstSampleFlagsForProxy(const GrRenderTargetProxy* rt) const {
1866
0
    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
0
    if (!isMSAAWithResolve && rt->supportsVkInputAttachment()) {
1871
0
        return GrDstSampleFlags::kRequiresTextureBarrier | GrDstSampleFlags::kAsInputAttachment;
1872
0
    }
1873
0
    return GrDstSampleFlags::kNone;
1874
0
}
1875
1876
0
uint64_t GrVkCaps::computeFormatKey(const GrBackendFormat& format) const {
1877
0
    VkFormat vkFormat;
1878
0
    SkAssertResult(GrBackendFormats::AsVkFormat(format, &vkFormat));
1879
1880
#ifdef SK_DEBUG
1881
    // We should never be trying to compute a key for an external format
1882
    const GrVkYcbcrConversionInfo* ycbcrInfo = GrBackendFormats::GetVkYcbcrConversionInfo(format);
1883
0
    SkASSERT(ycbcrInfo);
1884
0
    SkASSERT(!ycbcrInfo->isValid() || ycbcrInfo->fExternalFormat == 0);
1885
#endif
1886
1887
    // A VkFormat has a size of 64 bits.
1888
0
    return (uint64_t)vkFormat;
1889
0
}
Unexecuted instantiation: GrVkCaps::computeFormatKey(GrBackendFormat const&) const
Unexecuted instantiation: GrVkCaps::computeFormatKey(GrBackendFormat const&) const
1890
1891
GrCaps::SupportedRead GrVkCaps::onSupportedReadPixelsColorType(
1892
        GrColorType srcColorType, const GrBackendFormat& srcBackendFormat,
1893
0
        GrColorType dstColorType) const {
1894
0
    VkFormat vkFormat;
1895
0
    if (!GrBackendFormats::AsVkFormat(srcBackendFormat, &vkFormat)) {
1896
0
        return {GrColorType::kUnknown, 0};
1897
0
    }
1898
1899
0
    if (skgpu::VkFormatNeedsYcbcrSampler(vkFormat)) {
1900
0
        return {GrColorType::kUnknown, 0};
1901
0
    }
1902
1903
0
    SkTextureCompressionType compression = GrBackendFormatToCompressionType(srcBackendFormat);
1904
0
    if (compression != SkTextureCompressionType::kNone) {
1905
0
        return { SkTextureCompressionTypeIsOpaque(compression) ? GrColorType::kRGB_888x
1906
0
                                                        : GrColorType::kRGBA_8888, 0 };
1907
0
    }
1908
1909
    // The VkBufferImageCopy bufferOffset field must be both a multiple of 4 and of a single texel.
1910
0
    size_t offsetAlignment = align_to_4(skgpu::VkFormatBytesPerBlock(vkFormat));
1911
1912
0
    const auto& info = this->getFormatInfo(vkFormat);
1913
0
    for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1914
0
        const auto& ctInfo = info.fColorTypeInfos[i];
1915
0
        if (ctInfo.fColorType == srcColorType) {
1916
0
            return {ctInfo.fTransferColorType, offsetAlignment};
1917
0
        }
1918
0
    }
1919
0
    return {GrColorType::kUnknown, 0};
1920
0
}
1921
1922
0
int GrVkCaps::getFragmentUniformBinding() const {
1923
0
    return GrVkUniformHandler::kUniformBinding;
1924
0
}
1925
1926
0
int GrVkCaps::getFragmentUniformSet() const {
1927
0
    return GrVkUniformHandler::kUniformBufferDescSet;
1928
0
}
1929
1930
void GrVkCaps::addExtraSamplerKey(skgpu::KeyBuilder* b,
1931
                                  GrSamplerState samplerState,
1932
0
                                  const GrBackendFormat& format) const {
1933
0
    const GrVkYcbcrConversionInfo* ycbcrInfo = GrBackendFormats::GetVkYcbcrConversionInfo(format);
1934
0
    if (!ycbcrInfo) {
1935
0
        return;
1936
0
    }
1937
1938
0
    GrVkSampler::Key key = GrVkSampler::GenerateKey(samplerState, *ycbcrInfo);
1939
1940
0
    constexpr size_t numInts = (sizeof(key) + 3) / 4;
1941
0
    uint32_t tmp[numInts];
1942
0
    memcpy(tmp, &key, sizeof(key));
1943
1944
0
    for (size_t i = 0; i < numInts; ++i) {
1945
0
        b->add32(tmp[i]);
1946
0
    }
1947
0
}
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
 */
1962
GrProgramDesc GrVkCaps::makeDesc(GrRenderTarget* rt,
1963
                                 const GrProgramInfo& programInfo,
1964
0
                                 ProgramDescOverrideFlags overrideFlags) const {
1965
0
    GrProgramDesc desc;
1966
0
    GrProgramDesc::Build(&desc, programInfo, *this);
1967
1968
0
    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).
1975
0
    b.add32(GrVkGpu::kShader_PersistentCacheKeyType);
1976
1977
0
    GrVkRenderPass::SelfDependencyFlags selfDepFlags = GrVkRenderPass::SelfDependencyFlags::kNone;
1978
0
    if (programInfo.renderPassBarriers() & GrXferBarrierFlags::kBlend) {
1979
0
        selfDepFlags |= GrVkRenderPass::SelfDependencyFlags::kForNonCoherentAdvBlend;
1980
0
    }
1981
0
    if (programInfo.renderPassBarriers() & GrXferBarrierFlags::kTexture) {
1982
0
        selfDepFlags |= GrVkRenderPass::SelfDependencyFlags::kForInputAttachment;
1983
0
    }
1984
1985
0
    bool needsResolve = this->programInfoWillUseDiscardableMSAA(programInfo);
1986
1987
0
    bool forceLoadFromResolve =
1988
0
            overrideFlags & GrCaps::ProgramDescOverrideFlags::kVulkanHasResolveLoadSubpass;
1989
0
    SkASSERT(!forceLoadFromResolve || needsResolve);
1990
1991
0
    GrVkRenderPass::LoadFromResolve loadFromResolve = GrVkRenderPass::LoadFromResolve::kNo;
1992
0
    if (needsResolve && (programInfo.colorLoadOp() == GrLoadOp::kLoad || forceLoadFromResolve)) {
1993
0
        loadFromResolve = GrVkRenderPass::LoadFromResolve::kLoad;
1994
0
    }
1995
1996
0
    if (rt) {
1997
0
        GrVkRenderTarget* vkRT = (GrVkRenderTarget*) rt;
1998
1999
0
        SkASSERT(!needsResolve || (vkRT->resolveAttachment() &&
2000
0
                                   vkRT->resolveAttachment()->supportsInputAttachmentUsage()));
2001
2002
0
        bool needsStencil = programInfo.needsStencil() || programInfo.isStencilEnabled();
2003
        // TODO: support failure in getSimpleRenderPass
2004
0
        auto rp = vkRT->getSimpleRenderPass(needsResolve, needsStencil, selfDepFlags,
2005
0
                                            loadFromResolve);
2006
0
        SkASSERT(rp);
2007
0
        rp->genKey(&b);
2008
2009
#ifdef SK_DEBUG
2010
0
        if (!rp->isExternal()) {
2011
            // This is to ensure ReconstructAttachmentsDescriptor keeps matching
2012
            // getSimpleRenderPass' result
2013
0
            GrVkRenderPass::AttachmentsDescriptor attachmentsDescriptor;
2014
0
            GrVkRenderPass::AttachmentFlags attachmentFlags;
2015
0
            GrVkRenderTarget::ReconstructAttachmentsDescriptor(*this, programInfo,
2016
0
                                                               &attachmentsDescriptor,
2017
0
                                                               &attachmentFlags);
2018
0
            SkASSERT(rp->isCompatible(attachmentsDescriptor, attachmentFlags, selfDepFlags,
2019
0
                                      loadFromResolve));
2020
0
        }
2021
#endif
2022
0
    } else {
2023
0
        GrVkRenderPass::AttachmentsDescriptor attachmentsDescriptor;
2024
0
        GrVkRenderPass::AttachmentFlags attachmentFlags;
2025
0
        GrVkRenderTarget::ReconstructAttachmentsDescriptor(*this, programInfo,
2026
0
                                                           &attachmentsDescriptor,
2027
0
                                                           &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
0
        GrVkRenderPass::GenKey(&b, attachmentFlags, attachmentsDescriptor, selfDepFlags,
2033
0
                               loadFromResolve, 0);
2034
0
    }
2035
2036
0
    GrStencilSettings stencil = programInfo.nonGLStencilSettings();
2037
0
    stencil.genKey(&b, true);
2038
2039
0
    programInfo.pipeline().genKey(&b, *this);
2040
0
    b.add32(programInfo.numSamples());
2041
2042
    // Vulkan requires the full primitive type as part of its key
2043
0
    b.add32(programInfo.primitiveTypeKey());
2044
2045
0
    b.flush();
2046
0
    return desc;
2047
0
}
Unexecuted instantiation: GrVkCaps::makeDesc(GrRenderTarget*, GrProgramInfo const&, GrCaps::ProgramDescOverrideFlags) const
Unexecuted instantiation: GrVkCaps::makeDesc(GrRenderTarget*, GrProgramInfo const&, GrCaps::ProgramDescOverrideFlags) const
2048
2049
0
GrInternalSurfaceFlags GrVkCaps::getExtraSurfaceFlagsForDeferredRT() const {
2050
    // We always create vulkan RT with the input attachment flag;
2051
0
    return GrInternalSurfaceFlags::kVkRTSupportsInputAttachment;
2052
0
}
2053
2054
0
VkShaderStageFlags GrVkCaps::getPushConstantStageFlags() const {
2055
0
    VkShaderStageFlags stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
2056
0
    return stageFlags;
2057
0
}
2058
2059
template <size_t N>
2060
0
static bool intel_deviceID_present(const std::array<uint32_t, N>& array, uint32_t deviceID) {
2061
0
    return std::find(array.begin(), array.end(), deviceID) != array.end();
2062
0
}
Unexecuted instantiation: GrVkCaps.cpp:bool intel_deviceID_present<25ul>(std::__1::array<unsigned int, 25ul> const&, unsigned int)
Unexecuted instantiation: GrVkCaps.cpp:bool intel_deviceID_present<14ul>(std::__1::array<unsigned int, 14ul> const&, unsigned int)
Unexecuted instantiation: GrVkCaps.cpp:bool intel_deviceID_present<5ul>(std::__1::array<unsigned int, 5ul> const&, unsigned int)
Unexecuted instantiation: GrVkCaps.cpp:bool intel_deviceID_present<11ul>(std::__1::array<unsigned int, 11ul> const&, unsigned int)
Unexecuted instantiation: GrVkCaps.cpp:bool intel_deviceID_present<10ul>(std::__1::array<unsigned int, 10ul> const&, unsigned int)
2063
2064
2065
0
GrVkCaps::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
0
    static constexpr std::array<uint32_t, 25> kSkyLakeIDs = {
2071
0
        {0x1902, 0x1906, 0x190A, 0x190B, 0x190E, 0x1912, 0x1913,
2072
0
         0x1915, 0x1916, 0x1917, 0x191A, 0x191B, 0x191D, 0x191E,
2073
0
         0x1921, 0x1923, 0x1926, 0x1927, 0x192A, 0x192B, 0x192D,
2074
0
         0x1932, 0x193A, 0x193B, 0x193D}};
2075
0
    static constexpr std::array<uint32_t, 14> kIceLakeIDs = {
2076
0
        {0x8A50, 0x8A51, 0x8A52, 0x8A53, 0x8A54, 0x8A56, 0x8A57,
2077
0
         0x8A58, 0x8A59, 0x8A5A, 0x8A5B, 0x8A5C, 0x8A5D, 0x8A71}};
2078
0
    static constexpr  std::array<uint32_t, 5> kRocketLakeIDs = {
2079
0
        {0x4c8a, 0x4c8b, 0x4c8c, 0x4c90, 0x4c9a}};
2080
0
    static constexpr  std::array<uint32_t, 11> kTigerLakeIDs = {
2081
0
        {0x9A40, 0x9A49, 0x9A59, 0x9A60, 0x9A68, 0x9A70,
2082
0
         0x9A78, 0x9AC0, 0x9AC9, 0x9AD9, 0x9AF8}};
2083
0
    static constexpr  std::array<uint32_t, 10> kAlderLakeIDs = {
2084
0
        {0x4680, 0x4681, 0x4682, 0x4683, 0x4690,
2085
0
         0x4691, 0x4692, 0x4693, 0x4698, 0x4699}};
2086
2087
0
    if (intel_deviceID_present(kSkyLakeIDs, deviceID)) {
2088
0
        return IntelGPUType::kSkyLake;
2089
0
    }
2090
0
    if (intel_deviceID_present(kIceLakeIDs, deviceID)) {
2091
0
        return IntelGPUType::kIceLake;
2092
0
    }
2093
0
    if (intel_deviceID_present(kRocketLakeIDs, deviceID)) {
2094
0
        return IntelGPUType::kRocketLake;
2095
0
    }
2096
0
    if (intel_deviceID_present(kTigerLakeIDs, deviceID)) {
2097
0
        return IntelGPUType::kTigerLake;
2098
0
    }
2099
0
    if (intel_deviceID_present(kAlderLakeIDs, deviceID)) {
2100
0
        return IntelGPUType::kAlderLake;
2101
0
    }
2102
0
    return IntelGPUType::kOther;
2103
0
}
2104
2105
#if defined(GR_TEST_UTILS)
2106
0
std::vector<GrTest::TestFormatColorTypeCombination> GrVkCaps::getTestingCombinations() const {
2107
0
    std::vector<GrTest::TestFormatColorTypeCombination> combos = {
2108
0
        { GrColorType::kAlpha_8,          GrBackendFormats::MakeVk(VK_FORMAT_R8_UNORM)            },
2109
0
        { GrColorType::kBGR_565,          GrBackendFormats::MakeVk(VK_FORMAT_R5G6B5_UNORM_PACK16) },
2110
0
        { GrColorType::kRGB_565,          GrBackendFormats::MakeVk(VK_FORMAT_B5G6R5_UNORM_PACK16) },
2111
0
        { GrColorType::kABGR_4444,       GrBackendFormats::MakeVk(VK_FORMAT_R4G4B4A4_UNORM_PACK16)},
2112
0
        { GrColorType::kABGR_4444,       GrBackendFormats::MakeVk(VK_FORMAT_B4G4R4A4_UNORM_PACK16)},
2113
0
        { GrColorType::kRGBA_8888,        GrBackendFormats::MakeVk(VK_FORMAT_R8G8B8A8_UNORM)      },
2114
0
        { GrColorType::kRGBA_8888_SRGB,   GrBackendFormats::MakeVk(VK_FORMAT_R8G8B8A8_SRGB)       },
2115
0
        { GrColorType::kRGB_888x,         GrBackendFormats::MakeVk(VK_FORMAT_R8G8B8A8_UNORM)      },
2116
0
        { GrColorType::kRGB_888x,         GrBackendFormats::MakeVk(VK_FORMAT_B8G8R8A8_UNORM)      },
2117
0
        { GrColorType::kRGB_888x,         GrBackendFormats::MakeVk(VK_FORMAT_R8G8B8_UNORM)        },
2118
0
        { GrColorType::kRG_88,            GrBackendFormats::MakeVk(VK_FORMAT_R8G8_UNORM)          },
2119
0
        { GrColorType::kBGRA_8888,        GrBackendFormats::MakeVk(VK_FORMAT_B8G8R8A8_UNORM)      },
2120
0
        { GrColorType::kRGBA_1010102, GrBackendFormats::MakeVk(VK_FORMAT_A2B10G10R10_UNORM_PACK32)},
2121
0
        { GrColorType::kBGRA_1010102, GrBackendFormats::MakeVk(VK_FORMAT_A2R10G10B10_UNORM_PACK32)},
2122
0
        { GrColorType::kRGBA_10x6,
2123
0
          GrBackendFormats::MakeVk(VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16)},
2124
0
        { GrColorType::kGray_8,           GrBackendFormats::MakeVk(VK_FORMAT_R8_UNORM)            },
2125
0
        { GrColorType::kAlpha_F16,        GrBackendFormats::MakeVk(VK_FORMAT_R16_SFLOAT)          },
2126
0
        { GrColorType::kRGBA_F16,         GrBackendFormats::MakeVk(VK_FORMAT_R16G16B16A16_SFLOAT) },
2127
0
        { GrColorType::kRGBA_F16_Clamped, GrBackendFormats::MakeVk(VK_FORMAT_R16G16B16A16_SFLOAT) },
2128
0
        { GrColorType::kAlpha_16,         GrBackendFormats::MakeVk(VK_FORMAT_R16_UNORM)           },
2129
0
        { GrColorType::kRG_1616,          GrBackendFormats::MakeVk(VK_FORMAT_R16G16_UNORM)        },
2130
0
        { GrColorType::kRGBA_16161616,    GrBackendFormats::MakeVk(VK_FORMAT_R16G16B16A16_UNORM)  },
2131
0
        { GrColorType::kRG_F16,           GrBackendFormats::MakeVk(VK_FORMAT_R16G16_SFLOAT)       },
2132
        // These two compressed formats both have an effective colorType of kRGB_888x
2133
0
        { GrColorType::kRGB_888x,      GrBackendFormats::MakeVk(VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK)},
2134
0
        { GrColorType::kRGB_888x,         GrBackendFormats::MakeVk(VK_FORMAT_BC1_RGB_UNORM_BLOCK) },
2135
0
        { GrColorType::kRGBA_8888,        GrBackendFormats::MakeVk(VK_FORMAT_BC1_RGBA_UNORM_BLOCK)},
2136
0
    };
2137
2138
0
    return combos;
2139
0
}
2140
#endif