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