xref: /aosp_15_r20/external/skia/src/gpu/ganesh/mtl/GrMtlCaps.mm (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1/*
2 * Copyright 2017 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/mtl/GrMtlCaps.h"
9
10#include "include/core/SkRect.h"
11#include "include/core/SkTextureCompressionType.h"
12#include "include/gpu/ganesh/GrBackendSurface.h"
13#include "include/gpu/ganesh/mtl/GrMtlBackendSurface.h"
14#include "src/core/SkCompressedDataUtils.h"
15#include "src/core/SkReadBuffer.h"
16#include "src/gpu/KeyBuilder.h"
17#include "src/gpu/ganesh/GrBackendUtils.h"
18#include "src/gpu/ganesh/GrProcessor.h"
19#include "src/gpu/ganesh/GrProgramDesc.h"
20#include "src/gpu/ganesh/GrProgramInfo.h"
21#include "src/gpu/ganesh/GrRenderTarget.h"
22#include "src/gpu/ganesh/GrRenderTargetProxy.h"
23#include "src/gpu/ganesh/GrShaderCaps.h"
24#include "src/gpu/ganesh/GrSurfaceProxy.h"
25#include "src/gpu/ganesh/mtl/GrMtlRenderTarget.h"
26#include "src/gpu/ganesh/mtl/GrMtlTexture.h"
27#include "src/gpu/ganesh/mtl/GrMtlUtil.h"
28#include "src/gpu/mtl/MtlUtilsPriv.h"
29
30#if defined(GPU_TEST_UTILS)
31    #include "src/gpu/ganesh/TestFormatColorTypeCombination.h"
32#endif
33
34#if !__has_feature(objc_arc)
35#error This file must be compiled with Arc. Use -fobjc-arc flag
36#endif
37
38GR_NORETAIN_BEGIN
39
40GrMtlCaps::GrMtlCaps(const GrContextOptions& contextOptions, const id<MTLDevice> device)
41        : INHERITED(contextOptions) {
42    fShaderCaps = std::make_unique<GrShaderCaps>();
43
44    this->initGPUFamily(device);
45    this->initGrCaps(device);
46    this->initShaderCaps();
47    if (!contextOptions.fDisableDriverCorrectnessWorkarounds) {
48        this->applyDriverCorrectnessWorkarounds(contextOptions, device);
49    }
50
51    this->initFormatTable();
52    this->initStencilFormat(device);
53
54    // TODO: appears to be slow with Mac msaa8, disabled for now
55    fStoreAndMultisampleResolveSupport = (fGPUFamily == GPUFamily::kApple &&
56                                          fFamilyGroup >= 3);
57    // Also slow with non-Apple silicon
58    fPreferDiscardableMSAAAttachment = (fGPUFamily == GPUFamily::kApple);
59
60    this->finishInitialization(contextOptions);
61}
62
63// translates from older MTLFeatureSet interface to MTLGPUFamily interface
64bool GrMtlCaps::getGPUFamilyFromFeatureSet(id<MTLDevice> device,
65                                           GPUFamily* gpuFamily,
66                                           int* group) {
67// MTLFeatureSet is deprecated for newer versions of the SDK
68#if GR_METAL_SDK_VERSION < 300
69
70#if defined(SK_BUILD_FOR_MAC)
71    // Apple Silicon is only available in later OSes
72    *gpuFamily = GPUFamily::kMac;
73    // Mac OSX 14
74    if (@available(macOS 10.14, *)) {
75        if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily2_v1]) {
76            *group = 2;
77            return true;
78        }
79        if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v4]) {
80            *group = 1;
81            return true;
82        }
83    }
84    // Mac OSX 13
85    if (@available(macOS 10.13, *)) {
86        if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v3]) {
87            *group = 1;
88            return true;
89        }
90    }
91    // Mac OSX 12
92    if (@available(macOS 10.12, *)) {
93        if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v2]) {
94            *group = 1;
95            return true;
96        }
97    }
98    // Mac OSX 11
99    if (@available(macOS 10.11, *)) {
100        if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v1]) {
101            *group = 1;
102            return true;
103        }
104    }
105#elif defined(SK_BUILD_FOR_IOS)
106    // TODO: support tvOS
107   *gpuFamily = GPUFamily::kApple;
108    // iOS 12
109    if (@available(iOS 12.0, tvOS 12.0, *)) {
110        if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily5_v1]) {
111            *group = 5;
112            return true;
113        }
114        if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily4_v2]) {
115            *group = 4;
116            return true;
117        }
118        if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v4]) {
119            *group = 3;
120            return true;
121        }
122        if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily2_v5]) {
123            *group = 2;
124            return true;
125        }
126        if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily1_v5]) {
127            *group = 1;
128            return true;
129        }
130    }
131    // iOS 11
132    if (@available(iOS 11.0, tvOS 11.0, *)) {
133        if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily4_v1]) {
134            *group = 4;
135            return true;
136        }
137        if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v3]) {
138            *group = 3;
139            return true;
140        }
141        if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily2_v4]) {
142            *group = 2;
143            return true;
144        }
145        if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily1_v4]) {
146            *group = 1;
147            return true;
148        }
149    }
150    // iOS 10
151    if (@available(iOS 10.0, tvOS 10.0, *)) {
152        if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v2]) {
153            *group = 3;
154            return true;
155        }
156        if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily2_v3]) {
157            *group = 2;
158            return true;
159        }
160        if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily1_v3]) {
161            *group = 1;
162            return true;
163        }
164    }
165    // We don't support earlier OSes
166#endif
167
168#endif // GR_METAL_SDK_VERSION < 300
169
170    // No supported GPU families were found
171    return false;
172}
173
174bool GrMtlCaps::getGPUFamily(id<MTLDevice> device, GPUFamily* gpuFamily, int* group) {
175#if GR_METAL_SDK_VERSION >= 220
176    if (@available(macOS 10.15, iOS 13.0, tvOS 13.0, *)) {
177        // Apple Silicon
178#if GR_METAL_SDK_VERSION >= 230
179        if ([device supportsFamily:MTLGPUFamilyApple7]) {
180            *gpuFamily = GPUFamily::kApple;
181            *group = 7;
182            return true;
183        }
184#endif
185#ifdef SK_BUILD_FOR_IOS
186        if ([device supportsFamily:MTLGPUFamilyApple6]) {
187            *gpuFamily = GPUFamily::kApple;
188            *group = 6;
189            return true;
190        }
191        if ([device supportsFamily:MTLGPUFamilyApple5]) {
192            *gpuFamily = GPUFamily::kApple;
193            *group = 5;
194            return true;
195        }
196        if ([device supportsFamily:MTLGPUFamilyApple4]) {
197            *gpuFamily = GPUFamily::kApple;
198            *group = 4;
199            return true;
200        }
201        if ([device supportsFamily:MTLGPUFamilyApple3]) {
202            *gpuFamily = GPUFamily::kApple;
203            *group = 3;
204            return true;
205        }
206        if ([device supportsFamily:MTLGPUFamilyApple2]) {
207            *gpuFamily = GPUFamily::kApple;
208            *group = 2;
209            return true;
210        }
211        if ([device supportsFamily:MTLGPUFamilyApple1]) {
212            *gpuFamily = GPUFamily::kApple;
213            *group = 1;
214            return true;
215        }
216#endif
217
218        // Older Macs
219        // MTLGPUFamilyMac1, MTLGPUFamilyMacCatalyst1, and MTLGPUFamilyMacCatalyst2 are deprecated.
220        // However, some MTLGPUFamilyMac1 only hardware is still supported.
221        // MacCatalyst families have the same features as Mac, so treat them the same
222        if ([device supportsFamily:MTLGPUFamilyMac2] ||
223            [device supportsFamily:(MTLGPUFamily)4002/*MTLGPUFamilyMacCatalyst2*/]) {
224            *gpuFamily = GPUFamily::kMac;
225            *group = 2;
226            return true;
227        }
228        if ([device supportsFamily:(MTLGPUFamily)2001/*MTLGPUFamilyMac1*/] ||
229            [device supportsFamily:(MTLGPUFamily)4001/*MTLGPUFamilyMacCatalyst1*/]) {
230            *gpuFamily = GPUFamily::kMac;
231            *group = 1;
232            return true;
233        }
234    }
235#endif
236
237    // No supported GPU families were found
238    return false;
239}
240
241void GrMtlCaps::initGPUFamily(id<MTLDevice> device) {
242    if (@available(macOS 10.15, iOS 13.0, tvOS 13.0, *)) {
243        if (this->getGPUFamily(device, &fGPUFamily, &fFamilyGroup)) {
244            return;
245        }
246    } else {
247        if (this->getGPUFamilyFromFeatureSet(device, &fGPUFamily, &fFamilyGroup)) {
248            return;
249        }
250    }
251    // We don't know what this is, fall back to minimum defaults
252#ifdef SK_BUILD_FOR_MAC
253    fGPUFamily = GPUFamily::kMac;
254    fFamilyGroup = 1;
255#else
256    fGPUFamily = GPUFamily::kApple;
257    fFamilyGroup = 1;
258#endif
259}
260
261bool GrMtlCaps::canCopyAsBlit(MTLPixelFormat dstFormat, int dstSampleCount,
262                              MTLPixelFormat srcFormat, int srcSampleCount,
263                              const SkIRect& srcRect, const SkIPoint& dstPoint,
264                              bool areDstSrcSameObj) const {
265    if (!dstFormat || dstFormat != srcFormat) {
266        return false;
267    }
268    if ((dstSampleCount > 1 || srcSampleCount > 1) && (dstSampleCount != srcSampleCount)) {
269        return false;
270    }
271    if (areDstSrcSameObj) {
272        SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.x(), dstPoint.y(),
273                                            srcRect.width(), srcRect.height());
274        if (dstRect.intersect(srcRect)) {
275            return false;
276        }
277    }
278    return true;
279}
280
281bool GrMtlCaps::canCopyAsResolve(MTLPixelFormat dstFormat, int dstSampleCount,
282                                 MTLPixelFormat srcFormat, int srcSampleCount,
283                                 bool srcIsRenderTarget, const SkISize srcDimensions,
284                                 const SkIRect& srcRect,
285                                 const SkIPoint& dstPoint,
286                                 bool areDstSrcSameObj) const {
287    if (areDstSrcSameObj) {
288        return false;
289    }
290    if (dstFormat != srcFormat) {
291        return false;
292    }
293    if (dstSampleCount > 1 || srcSampleCount == 1 || !srcIsRenderTarget) {
294        return false;
295    }
296
297    // TODO: Support copying subrectangles
298    if (dstPoint != SkIPoint::Make(0, 0)) {
299        return false;
300    }
301    if (srcRect != SkIRect::MakeSize(srcDimensions)) {
302        return false;
303    }
304
305    return true;
306}
307
308bool GrMtlCaps::onCanCopySurface(const GrSurfaceProxy* dst, const SkIRect& dstRect,
309                                 const GrSurfaceProxy* src, const SkIRect& srcRect) const {
310    // Metal does not support scaling copies
311    if (srcRect.size() != dstRect.size()) {
312        return false;
313    }
314
315    int dstSampleCnt = 1;
316    int srcSampleCnt = 1;
317    if (const GrRenderTargetProxy* rtProxy = dst->asRenderTargetProxy()) {
318        dstSampleCnt = rtProxy->numSamples();
319    }
320    if (const GrRenderTargetProxy* rtProxy = src->asRenderTargetProxy()) {
321        srcSampleCnt = rtProxy->numSamples();
322    }
323
324    // TODO: need some way to detect whether the proxy is framebufferOnly
325
326    const SkIPoint dstPoint = dstRect.topLeft();
327    if (this->canCopyAsBlit(GrBackendFormatAsMTLPixelFormat(dst->backendFormat()), dstSampleCnt,
328                            GrBackendFormatAsMTLPixelFormat(src->backendFormat()), srcSampleCnt,
329                            srcRect, dstPoint, dst == src)) {
330        return true;
331    }
332    bool srcIsRenderTarget = src->asRenderTargetProxy();
333    MTLPixelFormat dstFormat = GrBackendFormatAsMTLPixelFormat(dst->backendFormat());
334    MTLPixelFormat srcFormat = GrBackendFormatAsMTLPixelFormat(src->backendFormat());
335    return this->canCopyAsResolve(dstFormat, dstSampleCnt,
336                                  srcFormat, srcSampleCnt,
337                                  srcIsRenderTarget, src->backingStoreDimensions(), srcRect,
338                                  dstPoint,
339                                  dst == src);
340}
341
342void GrMtlCaps::initGrCaps(id<MTLDevice> device) {
343#if defined(GPU_TEST_UTILS)
344    this->setDeviceName([[device name] UTF8String]);
345#endif
346
347    // Max vertex attribs is the same on all devices
348    fMaxVertexAttributes = 31;
349
350    // Metal does not support scissor + clear
351    fPerformPartialClearsAsDraws = true;
352
353    // We always copy in/out of a transfer buffer so it's trivial to support row bytes.
354    fReadPixelsRowBytesSupport = true;
355    fWritePixelsRowBytesSupport = true;
356    fTransferPixelsToRowBytesSupport = true;
357
358    // RenderTarget and Texture size
359    if (this->isMac() || fFamilyGroup >= 3) {
360        fMaxRenderTargetSize = 16384;
361    } else {
362        fMaxRenderTargetSize = 8192;
363    }
364    fMaxPreferredRenderTargetSize = fMaxRenderTargetSize;
365    fMaxTextureSize = fMaxRenderTargetSize;
366
367    fMaxPushConstantsSize = 4*1024;
368    fTransferBufferRowBytesAlignment = 1;
369
370    // This is documented to be 4 for all Macs. However, on Apple GPUs on Mac it appears there is
371    // no actual alignment requirement
372    // https://developer.apple.com/documentation/metal/mtlblitcommandencoder/1400767-copyfrombuffer
373    if (this->isMac()) {
374        fTransferFromBufferToBufferAlignment = 4;
375        // Buffer updates are sometimes implemented through transfers in GrMtlBuffer.
376        fBufferUpdateDataPreserveAlignment = 4;
377    }
378
379    // Metal buffers are initialized to zero (if not created with initial data)
380    fBuffersAreInitiallyZero = true;
381
382    // Init sample counts. All devices support 1 (i.e. 0 in skia).
383    fSampleCounts.push_back(1);
384    if (@available(iOS 9.0, tvOS 9.0, *)) {
385        for (auto sampleCnt : {2, 4, 8}) {
386            if ([device supportsTextureSampleCount:sampleCnt]) {
387                fSampleCounts.push_back(sampleCnt);
388            }
389        }
390    }
391
392    // Clamp to border is supported on Mac 10.12 and higher. It is not supported on iOS.
393    fClampToBorderSupport = false;
394#ifdef SK_BUILD_FOR_MAC
395    if (@available(macOS 10.12, *)) {
396        fClampToBorderSupport = true;
397    }
398#endif
399
400    // Starting with the assumption that there isn't a reason to not map small buffers.
401    fBufferMapThreshold = 0;
402
403    // Buffers are always fully mapped.
404    fMapBufferFlags =  kCanMap_MapFlag | kAsyncRead_MapFlag;
405
406    fOversizedStencilSupport = true;
407
408    fNPOTTextureTileSupport = true;  // always available in Metal
409    fMipmapSupport = true;   // always available in Metal
410    fAnisoSupport = true;   // always available in Metal
411
412    fReuseScratchTextures = true; // Assuming this okay
413
414    fTransferFromBufferToTextureSupport = true;
415    fTransferFromSurfaceToBufferSupport = true;
416    fTransferFromBufferToBufferSupport  = true;
417
418    fTextureBarrierSupport = false; // Need to figure out if we can do this
419
420    fSampleLocationsSupport = false;
421
422    if (@available(macOS 10.11, iOS 9.0, tvOS 9.0, *)) {
423        if (this->isMac() || fFamilyGroup >= 3) {
424            fDrawInstancedSupport = true;
425            fNativeDrawIndirectSupport = true;
426        }
427    }
428
429    fGpuTracingSupport = false;
430
431    bool supportsMTLEvent = false;
432    if (@available(macOS 10.14, iOS 12.0, tvOS 12.0, *)) {
433        supportsMTLEvent = true;
434    }
435    fSemaphoreSupport = supportsMTLEvent;
436    fBackendSemaphoreSupport = fSemaphoreSupport;
437    fFinishedProcAsyncCallbackSupport = true;
438
439    fCrossContextTextureSupport = true;
440    fHalfFloatVertexAttributeSupport = true;
441
442    fDynamicStateArrayGeometryProcessorTextureSupport = true;
443}
444
445static bool format_is_srgb(MTLPixelFormat format) {
446    switch (format) {
447        case MTLPixelFormatRGBA8Unorm_sRGB:
448        case MTLPixelFormatBGRA8Unorm_sRGB:
449            return true;
450        default:
451            return false;
452    }
453}
454
455bool GrMtlCaps::isFormatSRGB(const GrBackendFormat& format) const {
456    return format_is_srgb(GrBackendFormatAsMTLPixelFormat(format));
457}
458
459bool GrMtlCaps::isFormatTexturable(const GrBackendFormat& format, GrTextureType) const {
460    MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
461    return this->isFormatTexturable(mtlFormat);
462}
463
464bool GrMtlCaps::isFormatTexturable(MTLPixelFormat format) const {
465    const FormatInfo& formatInfo = this->getFormatInfo(format);
466    return SkToBool(FormatInfo::kTexturable_Flag & formatInfo.fFlags);
467}
468
469bool GrMtlCaps::isFormatAsColorTypeRenderable(GrColorType ct, const GrBackendFormat& format,
470                                              int sampleCount) const {
471    if (!this->isFormatRenderable(format, sampleCount)) {
472        return false;
473    }
474    MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
475    SkASSERT(mtlFormat != MTLPixelFormatInvalid);
476    const auto& info = this->getFormatInfo(mtlFormat);
477    if (!SkToBool(info.colorTypeFlags(ct) & ColorTypeInfo::kRenderable_Flag)) {
478        return false;
479    }
480    return true;
481}
482
483bool GrMtlCaps::isFormatRenderable(const GrBackendFormat& format, int sampleCount) const {
484    return this->isFormatRenderable(GrBackendFormatAsMTLPixelFormat(format), sampleCount);
485}
486
487bool GrMtlCaps::isFormatRenderable(MTLPixelFormat format, int sampleCount) const {
488    return sampleCount <= this->maxRenderTargetSampleCount(format);
489}
490
491int GrMtlCaps::maxRenderTargetSampleCount(const GrBackendFormat& format) const {
492    return this->maxRenderTargetSampleCount(GrBackendFormatAsMTLPixelFormat(format));
493}
494
495int GrMtlCaps::maxRenderTargetSampleCount(MTLPixelFormat format) const {
496    const FormatInfo& formatInfo = this->getFormatInfo(format);
497    if (formatInfo.fFlags & FormatInfo::kMSAA_Flag) {
498        return fSampleCounts[fSampleCounts.size() - 1];
499    } else if (formatInfo.fFlags & FormatInfo::kRenderable_Flag) {
500        return 1;
501    }
502    return 0;
503}
504
505int GrMtlCaps::getRenderTargetSampleCount(int requestedCount,
506                                          const GrBackendFormat& format) const {
507    MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
508
509    return this->getRenderTargetSampleCount(requestedCount, mtlFormat);
510}
511
512int GrMtlCaps::getRenderTargetSampleCount(int requestedCount, MTLPixelFormat format) const {
513    requestedCount = std::max(requestedCount, 1);
514    const FormatInfo& formatInfo = this->getFormatInfo(format);
515    if (!(formatInfo.fFlags & FormatInfo::kRenderable_Flag)) {
516        return 0;
517    }
518    if (formatInfo.fFlags & FormatInfo::kMSAA_Flag) {
519        int count = fSampleCounts.size();
520        for (int i = 0; i < count; ++i) {
521            if (fSampleCounts[i] >= requestedCount) {
522                return fSampleCounts[i];
523            }
524        }
525    }
526    return 1 == requestedCount ? 1 : 0;
527}
528
529void GrMtlCaps::initShaderCaps() {
530    GrShaderCaps* shaderCaps = fShaderCaps.get();
531
532    // Setting this true with the assumption that this cap will eventually mean we support varying
533    // precisions and not just via modifiers.
534    shaderCaps->fUsesPrecisionModifiers = true;
535    shaderCaps->fFlatInterpolationSupport = true;
536    // We haven't yet tested that using flat attributes perform well.
537    shaderCaps->fPreferFlatInterpolation = true;
538
539    shaderCaps->fShaderDerivativeSupport = true;
540    shaderCaps->fExplicitTextureLodSupport = true;
541
542    if (@available(macOS 10.12, iOS 11.0, tvOS 11.0, *)) {
543        shaderCaps->fDualSourceBlendingSupport = true;
544    } else {
545        shaderCaps->fDualSourceBlendingSupport = false;
546    }
547
548    // TODO(skia:8270): Re-enable this once bug 8270 is fixed. Will also need to remove asserts in
549    // GrMtlPipelineStateBuilder which assert we aren't using this feature.
550#if 0
551    if (this->isIOS()) {
552        shaderCaps->fFBFetchSupport = true;
553        shaderCaps->fFBFetchNeedsCustomOutput = true; // ??
554        shaderCaps->fFBFetchColorName = ""; // Somehow add [[color(0)]] to arguments to frag shader
555    }
556#endif
557    shaderCaps->fDstReadInShaderSupport = shaderCaps->fFBFetchSupport;
558
559    shaderCaps->fIntegerSupport = true;
560    shaderCaps->fNonsquareMatrixSupport = true;
561    shaderCaps->fInverseHyperbolicSupport = true;
562    shaderCaps->fVertexIDSupport = true;
563    shaderCaps->fInfinitySupport = true;
564    shaderCaps->fNonconstantArrayIndexSupport = true;
565
566    // Metal uses IEEE float and half floats so assuming those values here.
567    shaderCaps->fFloatIs32Bits = true;
568    shaderCaps->fHalfIs32Bits = false;
569
570    shaderCaps->fMaxFragmentSamplers = 16;
571}
572
573void GrMtlCaps::applyDriverCorrectnessWorkarounds(const GrContextOptions&, const id<MTLDevice>) {
574    // We don't have any active Metal workarounds.
575}
576
577// Define these so we can use them to initialize arrays and work around
578// the fact that these pixel formats are not always available.
579#define kMTLPixelFormatB5G6R5Unorm MTLPixelFormat(40)
580#define kMTLPixelFormatABGR4Unorm MTLPixelFormat(42)
581#define kMTLPixelFormatETC2_RGB8 MTLPixelFormat(180)
582
583// These are all the valid MTLPixelFormats that we support in Skia.  They are roughly ordered from
584// most frequently used to least to improve look up times in arrays.
585static constexpr MTLPixelFormat kMtlFormats[] = {
586    MTLPixelFormatRGBA8Unorm,
587    MTLPixelFormatR8Unorm,
588    MTLPixelFormatA8Unorm,
589    MTLPixelFormatBGRA8Unorm,
590    kMTLPixelFormatB5G6R5Unorm,
591    MTLPixelFormatRGBA16Float,
592    MTLPixelFormatR16Float,
593    MTLPixelFormatRG8Unorm,
594    MTLPixelFormatRGB10A2Unorm,
595    MTLPixelFormatBGR10A2Unorm,
596    kMTLPixelFormatABGR4Unorm,
597    MTLPixelFormatRGBA8Unorm_sRGB,
598    MTLPixelFormatR16Unorm,
599    MTLPixelFormatRG16Unorm,
600    kMTLPixelFormatETC2_RGB8,
601#ifdef SK_BUILD_FOR_MAC
602    MTLPixelFormatBC1_RGBA,
603#endif
604    MTLPixelFormatRGBA16Unorm,
605    MTLPixelFormatRG16Float,
606
607    MTLPixelFormatInvalid,
608};
609
610void GrMtlCaps::setColorType(GrColorType colorType, std::initializer_list<MTLPixelFormat> formats) {
611#ifdef SK_DEBUG
612    for (size_t i = 0; i < kNumMtlFormats; ++i) {
613        const auto& formatInfo = fFormatTable[i];
614        for (int j = 0; j < formatInfo.fColorTypeInfoCount; ++j) {
615            const auto& ctInfo = formatInfo.fColorTypeInfos[j];
616            if (ctInfo.fColorType == colorType) {
617                bool found = false;
618                for (auto it = formats.begin(); it != formats.end(); ++it) {
619                    if (kMtlFormats[i] == *it) {
620                        found = true;
621                    }
622                }
623                SkASSERT(found);
624            }
625        }
626    }
627#endif
628    int idx = static_cast<int>(colorType);
629    for (auto it = formats.begin(); it != formats.end(); ++it) {
630        const auto& info = this->getFormatInfo(*it);
631        for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
632            if (info.fColorTypeInfos[i].fColorType == colorType) {
633                fColorTypeToFormatTable[idx] = *it;
634                return;
635            }
636        }
637    }
638}
639
640size_t GrMtlCaps::GetFormatIndex(MTLPixelFormat pixelFormat) {
641    static_assert(std::size(kMtlFormats) == GrMtlCaps::kNumMtlFormats,
642                  "Size of kMtlFormats array must match static value in header");
643    for (size_t i = 0; i < GrMtlCaps::kNumMtlFormats; ++i) {
644        if (kMtlFormats[i] == pixelFormat) {
645            return i;
646        }
647    }
648    SK_ABORT("Invalid MTLPixelFormat: %d", static_cast<int>(pixelFormat));
649}
650
651void GrMtlCaps::initFormatTable() {
652    FormatInfo* info;
653
654    if (@available(macos 11.0, *)) {
655        SkASSERT(kMTLPixelFormatB5G6R5Unorm == MTLPixelFormatB5G6R5Unorm);
656        SkASSERT(kMTLPixelFormatABGR4Unorm == MTLPixelFormatABGR4Unorm);
657        SkASSERT(kMTLPixelFormatETC2_RGB8 == MTLPixelFormatETC2_RGB8);
658    }
659
660    // Format: R8Unorm
661    {
662        info = &fFormatTable[GetFormatIndex(MTLPixelFormatR8Unorm)];
663        info->fFlags = FormatInfo::kAllFlags;
664        info->fColorTypeInfoCount = 3;
665        info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
666        int ctIdx = 0;
667        // Format: R8Unorm, Surface: kAlpha_8
668        {
669            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
670            ctInfo.fColorType = GrColorType::kR_8;
671            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
672        }
673        // Format: R8Unorm, Surface: kAlpha_8
674        {
675            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
676            ctInfo.fColorType = GrColorType::kAlpha_8;
677            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
678            ctInfo.fReadSwizzle = skgpu::Swizzle("000r");
679            ctInfo.fWriteSwizzle = skgpu::Swizzle("a000");
680        }
681        // Format: R8Unorm, Surface: kGray_8
682        {
683            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
684            ctInfo.fColorType = GrColorType::kGray_8;
685            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
686            ctInfo.fReadSwizzle = skgpu::Swizzle("rrr1");
687        }
688    }
689
690    // Format: A8Unorm
691    {
692        info = &fFormatTable[GetFormatIndex(MTLPixelFormatA8Unorm)];
693        info->fFlags = FormatInfo::kTexturable_Flag;
694        info->fColorTypeInfoCount = 1;
695        info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
696        int ctIdx = 0;
697        // Format: A8Unorm, Surface: kAlpha_8
698        {
699            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
700            ctInfo.fColorType = GrColorType::kAlpha_8;
701            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
702        }
703    }
704
705    if (@available(macOS 11.0, iOS 8.0, tvOS 9.0, *)) {
706        if (this->isApple()) {
707            // Format: B5G6R5Unorm
708            {
709                info = &fFormatTable[GetFormatIndex(MTLPixelFormatB5G6R5Unorm)];
710                info->fFlags = FormatInfo::kAllFlags;
711                info->fColorTypeInfoCount = 1;
712                info->fColorTypeInfos =
713                        std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
714                int ctIdx = 0;
715                // Format: B5G6R5Unorm, Surface: kBGR_565
716                {
717                    auto& ctInfo = info->fColorTypeInfos[ctIdx++];
718                    ctInfo.fColorType = GrColorType::kBGR_565;
719                    ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag |
720                                    ColorTypeInfo::kRenderable_Flag;
721                }
722            }
723
724            // Format: ABGR4Unorm
725            {
726                info = &fFormatTable[GetFormatIndex(MTLPixelFormatABGR4Unorm)];
727                info->fFlags = FormatInfo::kAllFlags;
728                info->fColorTypeInfoCount = 1;
729                info->fColorTypeInfos =
730                        std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
731                int ctIdx = 0;
732                // Format: ABGR4Unorm, Surface: kABGR_4444
733                {
734                    auto& ctInfo = info->fColorTypeInfos[ctIdx++];
735                    ctInfo.fColorType = GrColorType::kABGR_4444;
736                    ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag |
737                                    ColorTypeInfo::kRenderable_Flag;
738                }
739            }
740        }
741    }
742
743    // Format: RGBA8Unorm
744    {
745        info = &fFormatTable[GetFormatIndex(MTLPixelFormatRGBA8Unorm)];
746        info->fFlags = FormatInfo::kAllFlags;
747        info->fColorTypeInfoCount = 2;
748        info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
749        int ctIdx = 0;
750        // Format: RGBA8Unorm, Surface: kRGBA_8888
751        {
752            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
753            ctInfo.fColorType = GrColorType::kRGBA_8888;
754            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
755        }
756        // Format: RGBA8Unorm, Surface: kRGB_888x
757        {
758            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
759            ctInfo.fColorType = GrColorType::kRGB_888x;
760            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
761            ctInfo.fReadSwizzle = skgpu::Swizzle::RGB1();
762        }
763    }
764
765    // Format: RG8Unorm
766    {
767        info = &fFormatTable[GetFormatIndex(MTLPixelFormatRG8Unorm)];
768        info->fFlags = FormatInfo::kAllFlags;
769        info->fColorTypeInfoCount = 1;
770        info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
771        int ctIdx = 0;
772        // Format: RG8Unorm, Surface: kRG_88
773        {
774            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
775            ctInfo.fColorType = GrColorType::kRG_88;
776            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
777        }
778    }
779
780    // Format: BGRA8Unorm
781    {
782        info = &fFormatTable[GetFormatIndex(MTLPixelFormatBGRA8Unorm)];
783        info->fFlags = FormatInfo::kAllFlags;
784        info->fColorTypeInfoCount = 1;
785        info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
786        int ctIdx = 0;
787        // Format: BGRA8Unorm, Surface: kBGRA_8888
788        {
789            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
790            ctInfo.fColorType = GrColorType::kBGRA_8888;
791            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
792        }
793    }
794
795    // Format: RGBA8Unorm_sRGB
796    {
797        info = &fFormatTable[GetFormatIndex(MTLPixelFormatRGBA8Unorm_sRGB)];
798        info->fFlags = FormatInfo::kAllFlags;
799        info->fColorTypeInfoCount = 1;
800        info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
801        int ctIdx = 0;
802        // Format: RGBA8Unorm_sRGB, Surface: kRGBA_8888_SRGB
803        {
804            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
805            ctInfo.fColorType = GrColorType::kRGBA_8888_SRGB;
806            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
807        }
808    }
809
810    // Format: RGB10A2Unorm
811    {
812        info = &fFormatTable[GetFormatIndex(MTLPixelFormatRGB10A2Unorm)];
813        if (this->isMac() || fFamilyGroup >= 3) {
814            info->fFlags = FormatInfo::kAllFlags;
815        } else {
816            info->fFlags = FormatInfo::kTexturable_Flag;
817        }
818        info->fColorTypeInfoCount = 2;
819        info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
820        int ctIdx = 0;
821        // Format: RGB10A2Unorm, Surface: kRGBA_1010102
822        {
823            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
824            ctInfo.fColorType = GrColorType::kRGBA_1010102;
825            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
826        }
827        // Format: RGB10A2Unorm, Surface: kRGB_101010x
828        {
829            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
830            ctInfo.fColorType = GrColorType::kRGB_101010x;
831            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
832            ctInfo.fReadSwizzle = skgpu::Swizzle::RGB1();
833        }
834    }
835
836    // Format: BGR10A2Unorm
837    if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
838        info = &fFormatTable[GetFormatIndex(MTLPixelFormatBGR10A2Unorm)];
839        if (this->isMac() && fFamilyGroup == 1) {
840            info->fFlags = FormatInfo::kTexturable_Flag;
841        } else {
842            info->fFlags = FormatInfo::kAllFlags;
843        }
844        info->fColorTypeInfoCount = 1;
845        info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
846        int ctIdx = 0;
847        // Format: BGR10A2Unorm, Surface: kBGRA_1010102
848        {
849            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
850            ctInfo.fColorType = GrColorType::kBGRA_1010102;
851            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
852        }
853    }
854
855    // Format: R16Float
856    {
857        info = &fFormatTable[GetFormatIndex(MTLPixelFormatR16Float)];
858        info->fFlags = FormatInfo::kAllFlags;
859        info->fColorTypeInfoCount = 1;
860        info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
861        int ctIdx = 0;
862        // Format: R16Float, Surface: kAlpha_F16
863        {
864            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
865            ctInfo.fColorType = GrColorType::kAlpha_F16;
866            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
867            ctInfo.fReadSwizzle = skgpu::Swizzle("000r");
868            ctInfo.fWriteSwizzle = skgpu::Swizzle("a000");
869        }
870    }
871
872    // Format: RGBA16Float
873    {
874        info = &fFormatTable[GetFormatIndex(MTLPixelFormatRGBA16Float)];
875        info->fFlags = FormatInfo::kAllFlags;
876        info->fColorTypeInfoCount = 3;
877        info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
878        int ctIdx = 0;
879        // Format: RGBA16Float, Surface: kRGBA_F16
880        {
881            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
882            ctInfo.fColorType = GrColorType::kRGBA_F16;
883            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
884        }
885        // Format: RGBA16Float, Surface: kRGBA_F16_Clamped
886        {
887            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
888            ctInfo.fColorType = GrColorType::kRGBA_F16_Clamped;
889            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
890        }
891        // Format: RGBA16Float, Surface: kRGB_F16F16F16x
892        {
893            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
894            ctInfo.fColorType = GrColorType::kRGB_F16F16F16x;
895            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
896            ctInfo.fReadSwizzle = skgpu::Swizzle::RGB1();
897        }
898    }
899
900    // Format: R16Unorm
901    {
902        info = &fFormatTable[GetFormatIndex(MTLPixelFormatR16Unorm)];
903        if (this->isMac()) {
904            info->fFlags = FormatInfo::kAllFlags;
905        } else {
906            info->fFlags = FormatInfo::kTexturable_Flag | FormatInfo::kRenderable_Flag;
907        }
908        info->fColorTypeInfoCount = 1;
909        info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
910        int ctIdx = 0;
911        // Format: R16Unorm, Surface: kAlpha_16
912        {
913            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
914            ctInfo.fColorType = GrColorType::kAlpha_16;
915            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
916            ctInfo.fReadSwizzle = skgpu::Swizzle("000r");
917            ctInfo.fWriteSwizzle = skgpu::Swizzle("a000");
918        }
919    }
920
921    // Format: RG16Unorm
922    {
923        info = &fFormatTable[GetFormatIndex(MTLPixelFormatRG16Unorm)];
924        if (this->isMac()) {
925            info->fFlags = FormatInfo::kAllFlags;
926        } else {
927            info->fFlags = FormatInfo::kTexturable_Flag | FormatInfo::kRenderable_Flag;
928        }
929        info->fColorTypeInfoCount = 1;
930        info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
931        int ctIdx = 0;
932        // Format: RG16Unorm, Surface: kRG_1616
933        {
934            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
935            ctInfo.fColorType = GrColorType::kRG_1616;
936            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
937        }
938    }
939
940    if (@available(macOS 11.0, iOS 8.0, tvOS 9.0, *)) {
941        if (this->isApple()) {
942            // ETC2_RGB8
943            info = &fFormatTable[GetFormatIndex(MTLPixelFormatETC2_RGB8)];
944            info->fFlags = FormatInfo::kTexturable_Flag;
945            // NO supported colorTypes
946        }
947    }
948#ifdef SK_BUILD_FOR_MAC
949    if (this->isMac()) {
950        // BC1_RGBA
951        info = &fFormatTable[GetFormatIndex(MTLPixelFormatBC1_RGBA)];
952        info->fFlags = FormatInfo::kTexturable_Flag;
953        // NO supported colorTypes
954    }
955#endif
956
957    // Format: RGBA16Unorm
958    {
959        info = &fFormatTable[GetFormatIndex(MTLPixelFormatRGBA16Unorm)];
960        if (this->isMac()) {
961            info->fFlags = FormatInfo::kAllFlags;
962        } else {
963            info->fFlags = FormatInfo::kTexturable_Flag | FormatInfo::kRenderable_Flag;
964        }
965        info->fColorTypeInfoCount = 1;
966        info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
967        int ctIdx = 0;
968        // Format: RGBA16Unorm, Surface: kRGBA_16161616
969        {
970            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
971            ctInfo.fColorType = GrColorType::kRGBA_16161616;
972            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
973        }
974    }
975
976    // Format: RG16Float
977    {
978        info = &fFormatTable[GetFormatIndex(MTLPixelFormatRG16Float)];
979        info->fFlags = FormatInfo::kAllFlags;
980        info->fColorTypeInfoCount = 1;
981        info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
982        int ctIdx = 0;
983        // Format: RG16Float, Surface: kRG_F16
984        {
985            auto& ctInfo = info->fColorTypeInfos[ctIdx++];
986            ctInfo.fColorType = GrColorType::kRG_F16;
987            ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
988        }
989    }
990
991    ////////////////////////////////////////////////////////////////////////////
992    // Map GrColorTypes (used for creating GrSurfaces) to MTLPixelFormats. The order in which the
993    // formats are passed into the setColorType function indicates the priority in selecting which
994    // format we use for a given GrcolorType.
995
996    std::fill_n(fColorTypeToFormatTable, kGrColorTypeCnt, MTLPixelFormatInvalid);
997
998    this->setColorType(GrColorType::kAlpha_8,           { MTLPixelFormatR8Unorm,
999                                                          MTLPixelFormatA8Unorm });
1000    if (@available(macOS 11.0, iOS 8.0, tvOS 9.0, *)) {
1001        if (this->isApple()) {
1002            this->setColorType(GrColorType::kBGR_565,   { MTLPixelFormatB5G6R5Unorm });
1003            this->setColorType(GrColorType::kABGR_4444, { MTLPixelFormatABGR4Unorm });
1004        }
1005    }
1006    this->setColorType(GrColorType::kRGBA_8888,         { MTLPixelFormatRGBA8Unorm });
1007    this->setColorType(GrColorType::kRGBA_8888_SRGB,    { MTLPixelFormatRGBA8Unorm_sRGB });
1008    this->setColorType(GrColorType::kRGB_888x,          { MTLPixelFormatRGBA8Unorm });
1009    this->setColorType(GrColorType::kRG_88,             { MTLPixelFormatRG8Unorm });
1010    this->setColorType(GrColorType::kBGRA_8888,         { MTLPixelFormatBGRA8Unorm });
1011    this->setColorType(GrColorType::kRGBA_1010102,      { MTLPixelFormatRGB10A2Unorm });
1012    if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
1013        this->setColorType(GrColorType::kBGRA_1010102,  { MTLPixelFormatBGR10A2Unorm });
1014    }
1015    this->setColorType(GrColorType::kRGB_101010x,       { MTLPixelFormatRGB10A2Unorm });
1016    this->setColorType(GrColorType::kGray_8,            { MTLPixelFormatR8Unorm });
1017    this->setColorType(GrColorType::kAlpha_F16,         { MTLPixelFormatR16Float });
1018    this->setColorType(GrColorType::kRGBA_F16,          { MTLPixelFormatRGBA16Float });
1019    this->setColorType(GrColorType::kRGBA_F16_Clamped,  { MTLPixelFormatRGBA16Float });
1020    this->setColorType(GrColorType::kRGB_F16F16F16x,    { MTLPixelFormatRGBA16Float });
1021    this->setColorType(GrColorType::kAlpha_16,          { MTLPixelFormatR16Unorm });
1022    this->setColorType(GrColorType::kRG_1616,           { MTLPixelFormatRG16Unorm });
1023    this->setColorType(GrColorType::kRGBA_16161616,     { MTLPixelFormatRGBA16Unorm });
1024    this->setColorType(GrColorType::kRG_F16,            { MTLPixelFormatRG16Float });
1025}
1026
1027void GrMtlCaps::initStencilFormat(id<MTLDevice> physDev) {
1028    fPreferredStencilFormat = MTLPixelFormatStencil8;
1029}
1030
1031bool GrMtlCaps::onSurfaceSupportsWritePixels(const GrSurface* surface) const {
1032    if (auto rt = surface->asRenderTarget()) {
1033        return rt->numSamples() <= 1 && SkToBool(surface->asTexture());
1034    }
1035    return true;
1036}
1037
1038GrCaps::SurfaceReadPixelsSupport GrMtlCaps::surfaceSupportsReadPixels(
1039        const GrSurface* surface) const {
1040    if (auto tex = static_cast<const GrMtlTexture*>(surface->asTexture())) {
1041        // We disallow reading back directly from compressed textures.
1042        if (skgpu::MtlFormatIsCompressed(tex->attachment()->mtlFormat())) {
1043            return SurfaceReadPixelsSupport::kCopyToTexture2D;
1044        }
1045    }
1046
1047    if (auto mtlRT = static_cast<const GrMtlRenderTarget*>(surface->asRenderTarget())) {
1048        if (mtlRT->numSamples() > 1 && !mtlRT->resolveAttachment()) {
1049            return SurfaceReadPixelsSupport::kCopyToTexture2D;
1050        }
1051    }
1052    return SurfaceReadPixelsSupport::kSupported;
1053}
1054
1055GrCaps::DstCopyRestrictions GrMtlCaps::getDstCopyRestrictions(const GrRenderTargetProxy* src,
1056                                                              GrColorType ct) const {
1057    // If the src is a MSAA RT then the only supported copy action (not considering falling back
1058    // to a draw) is to resolve from the MSAA src to the non-MSAA dst. Currently we only support
1059    // resolving the entire texture to a resolve buffer of the same size.
1060    DstCopyRestrictions restrictions = {};
1061    if (auto rtProxy = src->asRenderTargetProxy()) {
1062        if (rtProxy->numSamples() > 1) {
1063            restrictions.fMustCopyWholeSrc = true;
1064            restrictions.fRectsMustMatch = GrSurfaceProxy::RectsMustMatch::kYes;
1065        }
1066    }
1067    return restrictions;
1068}
1069
1070bool GrMtlCaps::onAreColorTypeAndFormatCompatible(GrColorType ct,
1071                                                  const GrBackendFormat& format) const {
1072    MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
1073
1074    const auto& info = this->getFormatInfo(mtlFormat);
1075    for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1076        if (info.fColorTypeInfos[i].fColorType == ct) {
1077            return true;
1078        }
1079    }
1080    return false;
1081}
1082
1083GrBackendFormat GrMtlCaps::onGetDefaultBackendFormat(GrColorType ct) const {
1084    MTLPixelFormat format = this->getFormatFromColorType(ct);
1085    if (!format) {
1086        return {};
1087    }
1088    return GrBackendFormats::MakeMtl(format);
1089}
1090
1091GrBackendFormat GrMtlCaps::getBackendFormatFromCompressionType(
1092        SkTextureCompressionType compressionType) const {
1093    switch (compressionType) {
1094        case SkTextureCompressionType::kNone:
1095            return {};
1096        case SkTextureCompressionType::kETC2_RGB8_UNORM:
1097            if (@available(macOS 11.0, *)) {
1098                if (this->isApple()) {
1099                    return GrBackendFormats::MakeMtl(MTLPixelFormatETC2_RGB8);
1100                } else {
1101                    return {};
1102                }
1103            } else {
1104                return {};
1105            }
1106        case SkTextureCompressionType::kBC1_RGB8_UNORM:
1107            // Metal only supports the RGBA BC1 variant (see following)
1108            return {};
1109        case SkTextureCompressionType::kBC1_RGBA8_UNORM:
1110#ifdef SK_BUILD_FOR_MAC
1111            if (this->isMac()) {
1112                return GrBackendFormats::MakeMtl(MTLPixelFormatBC1_RGBA);
1113            } else {
1114                return {};
1115            }
1116#else
1117            return {};
1118#endif
1119
1120    }
1121    SK_ABORT("Invalid compression type");
1122}
1123
1124skgpu::Swizzle GrMtlCaps::onGetReadSwizzle(const GrBackendFormat& format,
1125                                           GrColorType colorType) const {
1126    MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
1127    SkASSERT(mtlFormat != MTLPixelFormatInvalid);
1128    const auto& info = this->getFormatInfo(mtlFormat);
1129    for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1130        const auto& ctInfo = info.fColorTypeInfos[i];
1131        if (ctInfo.fColorType == colorType) {
1132            return ctInfo.fReadSwizzle;
1133        }
1134    }
1135    SkDEBUGFAILF("Illegal color type (%d) and format (%d) combination.", (int)colorType,
1136                 static_cast<int>(mtlFormat));
1137    return {};
1138}
1139
1140skgpu::Swizzle GrMtlCaps::getWriteSwizzle(const GrBackendFormat& format,
1141                                          GrColorType colorType) const {
1142    MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
1143    SkASSERT(mtlFormat != MTLPixelFormatInvalid);
1144    const auto& info = this->getFormatInfo(mtlFormat);
1145    for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1146        const auto& ctInfo = info.fColorTypeInfos[i];
1147        if (ctInfo.fColorType == colorType) {
1148            return ctInfo.fWriteSwizzle;
1149        }
1150    }
1151    SkDEBUGFAILF("Illegal color type (%d) and format (%d) combination.", (int)colorType,
1152                 static_cast<int>(mtlFormat));
1153    return {};
1154}
1155
1156uint64_t GrMtlCaps::computeFormatKey(const GrBackendFormat& format) const {
1157    MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
1158    SkASSERT(mtlFormat != MTLPixelFormatInvalid);
1159    // A MTLPixelFormat is an NSUInteger type which is documented to be 32 bits in 32 bit
1160    // applications and 64 bits in 64 bit applications. So it should fit in an uint64_t, but adding
1161    // the assert heere to make sure.
1162    static_assert(sizeof(MTLPixelFormat) <= sizeof(uint64_t));
1163    return (uint64_t)mtlFormat;
1164}
1165
1166GrCaps::SupportedWrite GrMtlCaps::supportedWritePixelsColorType(
1167        GrColorType surfaceColorType, const GrBackendFormat& surfaceFormat,
1168        GrColorType srcColorType) const {
1169    // Metal requires the destination offset for copyFromTexture to be a multiple of the textures
1170    // pixels size.
1171    size_t offsetAlignment = GrColorTypeBytesPerPixel(surfaceColorType);
1172
1173    const auto& info = this->getFormatInfo(GrBackendFormatAsMTLPixelFormat(surfaceFormat));
1174    for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1175        const auto& ctInfo = info.fColorTypeInfos[i];
1176        if (ctInfo.fColorType == surfaceColorType) {
1177            return {surfaceColorType, offsetAlignment};
1178        }
1179    }
1180    return {GrColorType::kUnknown, 0};
1181}
1182
1183GrCaps::SupportedRead GrMtlCaps::onSupportedReadPixelsColorType(
1184        GrColorType srcColorType, const GrBackendFormat& srcBackendFormat,
1185        GrColorType dstColorType) const {
1186    SkTextureCompressionType compression = GrBackendFormatToCompressionType(srcBackendFormat);
1187    if (compression != SkTextureCompressionType::kNone) {
1188#ifdef SK_BUILD_FOR_IOS
1189        // Reading back to kRGB_888x doesn't work on Metal/iOS (skbug.com/9839)
1190        return { GrColorType::kUnknown, 0 };
1191#else
1192        return { SkTextureCompressionTypeIsOpaque(compression) ? GrColorType::kRGB_888x
1193                                                        : GrColorType::kRGBA_8888, 0 };
1194#endif
1195    }
1196
1197    // Metal requires the destination offset for copyFromTexture to be a multiple of the textures
1198    // pixels size.
1199    size_t offsetAlignment = GrColorTypeBytesPerPixel(srcColorType);
1200    MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(srcBackendFormat);
1201
1202    const auto& info = this->getFormatInfo(mtlFormat);
1203    for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1204        const auto& ctInfo = info.fColorTypeInfos[i];
1205        if (ctInfo.fColorType == srcColorType) {
1206            return {srcColorType, offsetAlignment};
1207        }
1208    }
1209    return {GrColorType::kUnknown, 0};
1210}
1211
1212/**
1213 * For Metal we want to cache the entire pipeline for reuse of draws. The Desc here holds all
1214 * the information needed to differentiate one pipeline from another.
1215 *
1216 * The GrProgramDesc contains all the information need to create the actual shaders for the
1217 * pipeline.
1218 *
1219 * For Metal we need to add to the GrProgramDesc to include the rest of the state on the
1220 * pipeline. This includes blending information and primitive type. The pipeline is immutable
1221 * so any remaining dynamic state is set via the MtlRenderCmdEncoder.
1222 */
1223GrProgramDesc GrMtlCaps::makeDesc(GrRenderTarget*, const GrProgramInfo& programInfo,
1224                                  ProgramDescOverrideFlags overrideFlags) const {
1225    SkASSERT(overrideFlags == ProgramDescOverrideFlags::kNone);
1226    GrProgramDesc desc;
1227    GrProgramDesc::Build(&desc, programInfo, *this);
1228
1229    skgpu::KeyBuilder b(desc.key());
1230
1231    // If ordering here is changed, update getStencilPixelFormat() below
1232    b.add32(GrBackendFormats::AsMtlFormat(programInfo.backendFormat()));
1233
1234    b.add32(programInfo.numSamples());
1235
1236    b.add32(programInfo.needsStencil() ? this->preferredStencilFormat() : MTLPixelFormatInvalid);
1237    b.add32((uint32_t)programInfo.isStencilEnabled());
1238    // Stencil samples don't seem to be tracked in the MTLRenderPipeline
1239
1240    programInfo.pipeline().genKey(&b, *this);
1241
1242    b.add32(programInfo.primitiveTypeKey());
1243
1244    b.flush();
1245    return desc;
1246}
1247
1248MTLPixelFormat GrMtlCaps::getStencilPixelFormat(const GrProgramDesc& desc) const {
1249    // Set up read buffer to point to platform-dependent part of the key
1250    SkReadBuffer readBuffer(desc.asKey() + desc.initialKeyLength()/sizeof(uint32_t),
1251                            desc.keyLength() - desc.initialKeyLength());
1252    // skip backend format
1253    readBuffer.readUInt();
1254    // skip raster samples
1255    readBuffer.readUInt();
1256
1257    return (MTLPixelFormat) readBuffer.readUInt();
1258}
1259
1260bool GrMtlCaps::renderTargetSupportsDiscardableMSAA(const GrMtlRenderTarget* rt) const {
1261    return rt->resolveAttachment() &&
1262           !rt->resolveAttachment()->framebufferOnly() &&
1263           (rt->numSamples() > 1 && this->preferDiscardableMSAAAttachment());
1264}
1265
1266#if defined(GPU_TEST_UTILS)
1267std::vector<GrTest::TestFormatColorTypeCombination> GrMtlCaps::getTestingCombinations() const {
1268    std::vector<GrTest::TestFormatColorTypeCombination> combos = {
1269        { GrColorType::kAlpha_8,          GrBackendFormats::MakeMtl(MTLPixelFormatA8Unorm)         },
1270        { GrColorType::kAlpha_8,          GrBackendFormats::MakeMtl(MTLPixelFormatR8Unorm)         },
1271        { GrColorType::kBGR_565,          GrBackendFormats::MakeMtl(kMTLPixelFormatB5G6R5Unorm)    },
1272        { GrColorType::kABGR_4444,        GrBackendFormats::MakeMtl(kMTLPixelFormatABGR4Unorm)     },
1273        { GrColorType::kRGBA_8888,        GrBackendFormats::MakeMtl(MTLPixelFormatRGBA8Unorm)      },
1274        { GrColorType::kRGBA_8888_SRGB,   GrBackendFormats::MakeMtl(MTLPixelFormatRGBA8Unorm_sRGB) },
1275        { GrColorType::kRGB_888x,         GrBackendFormats::MakeMtl(MTLPixelFormatRGBA8Unorm)      },
1276        { GrColorType::kRGB_888x,         GrBackendFormats::MakeMtl(kMTLPixelFormatETC2_RGB8)      },
1277#ifdef SK_BUILD_FOR_MAC
1278        { GrColorType::kRGBA_8888,        GrBackendFormats::MakeMtl(MTLPixelFormatBC1_RGBA)        },
1279#endif
1280        { GrColorType::kRG_88,            GrBackendFormats::MakeMtl(MTLPixelFormatRG8Unorm)        },
1281        { GrColorType::kBGRA_8888,        GrBackendFormats::MakeMtl(MTLPixelFormatBGRA8Unorm)      },
1282        { GrColorType::kRGBA_1010102,     GrBackendFormats::MakeMtl(MTLPixelFormatRGB10A2Unorm)    },
1283        { GrColorType::kBGRA_1010102,     GrBackendFormats::MakeMtl(MTLPixelFormatBGR10A2Unorm)    },
1284        { GrColorType::kRGB_101010x,      GrBackendFormats::MakeMtl(MTLPixelFormatRGB10A2Unorm)    },
1285        { GrColorType::kGray_8,           GrBackendFormats::MakeMtl(MTLPixelFormatR8Unorm)         },
1286        { GrColorType::kAlpha_F16,        GrBackendFormats::MakeMtl(MTLPixelFormatR16Float)        },
1287        { GrColorType::kRGBA_F16,         GrBackendFormats::MakeMtl(MTLPixelFormatRGBA16Float)     },
1288        { GrColorType::kRGBA_F16_Clamped, GrBackendFormats::MakeMtl(MTLPixelFormatRGBA16Float)     },
1289        { GrColorType::kRGB_F16F16F16x,   GrBackendFormats::MakeMtl(MTLPixelFormatRGBA16Float)     },
1290        { GrColorType::kAlpha_16,         GrBackendFormats::MakeMtl(MTLPixelFormatR16Unorm)        },
1291        { GrColorType::kRG_1616,          GrBackendFormats::MakeMtl(MTLPixelFormatRG16Unorm)       },
1292        { GrColorType::kRGBA_16161616,    GrBackendFormats::MakeMtl(MTLPixelFormatRGBA16Unorm)     },
1293        { GrColorType::kRG_F16,           GrBackendFormats::MakeMtl(MTLPixelFormatRG16Float)       },
1294    };
1295
1296    return combos;
1297}
1298#endif
1299
1300#ifdef SK_ENABLE_DUMP_GPU
1301#include "src/utils/SkJSONWriter.h"
1302void GrMtlCaps::onDumpJSON(SkJSONWriter* writer) const {
1303
1304    // We are called by the base class, which has already called beginObject(). We choose to nest
1305    // all of our caps information in a named sub-object.
1306    writer->beginObject("Metal caps");
1307
1308    writer->beginObject("Preferred Stencil Format");
1309    writer->appendS32("stencil bits", GrMtlFormatStencilBits(fPreferredStencilFormat));
1310    writer->appendS32("total bytes", skgpu::MtlFormatBytesPerBlock(fPreferredStencilFormat));
1311    writer->endObject();
1312
1313    switch (fGPUFamily) {
1314        case GPUFamily::kMac:
1315            writer->appendNString("GPU Family", "Mac");
1316            break;
1317        case GPUFamily::kApple:
1318            writer->appendNString("GPU Family", "Apple");
1319            break;
1320        default:
1321            writer->appendNString("GPU Family", "unknown");
1322            break;
1323    }
1324    writer->appendS32("Family Group", fFamilyGroup);
1325
1326    writer->beginArray("Sample Counts");
1327    for (int v : fSampleCounts) {
1328        writer->appendS32(nullptr, v);
1329    }
1330    writer->endArray();
1331
1332    writer->endObject();
1333}
1334#else
1335void GrMtlCaps::onDumpJSON(SkJSONWriter* writer) const { }
1336#endif
1337
1338GR_NORETAIN_END
1339