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