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