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