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