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