Home | History | Annotate | Download | only in mtl
      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 "GrMtlCaps.h"
      9 
     10 #include "GrBackendSurface.h"
     11 #include "GrMtlUtil.h"
     12 #include "GrRenderTargetProxy.h"
     13 #include "GrShaderCaps.h"
     14 #include "GrSurfaceProxy.h"
     15 #include "SkRect.h"
     16 
     17 GrMtlCaps::GrMtlCaps(const GrContextOptions& contextOptions, const id<MTLDevice> device,
     18                      MTLFeatureSet featureSet)
     19         : INHERITED(contextOptions) {
     20     fShaderCaps.reset(new GrShaderCaps(contextOptions));
     21 
     22     this->initFeatureSet(featureSet);
     23     this->initGrCaps(device);
     24     this->initShaderCaps();
     25     this->initConfigTable();
     26     this->initStencilFormat(device);
     27 
     28     this->applyOptionsOverrides(contextOptions);
     29     fShaderCaps->applyOptionsOverrides(contextOptions);
     30 
     31     // The following are disabled due to the unfinished Metal backend, not because Metal itself
     32     // doesn't support it.
     33     fBlacklistCoverageCounting = true;   // CCPR shaders have some incompatabilities with SkSLC
     34     fFenceSyncSupport = false;           // Fences are not implemented yet
     35     fMipMapSupport = false;              // GrMtlGpu::onRegenerateMipMapLevels() not implemented
     36     fMultisampleDisableSupport = true;   // MSAA and resolving not implemented yet
     37     fDiscardRenderTargetSupport = false; // GrMtlGpuCommandBuffer::discard() not implemented
     38     fCrossContextTextureSupport = false; // GrMtlGpu::prepareTextureForCrossContextUsage() not impl
     39 }
     40 
     41 void GrMtlCaps::initFeatureSet(MTLFeatureSet featureSet) {
     42     // Mac OSX
     43 #ifdef SK_BUILD_FOR_MAC
     44     if (MTLFeatureSet_OSX_GPUFamily1_v2 == featureSet) {
     45         fPlatform = Platform::kMac;
     46         fFamilyGroup = 1;
     47         fVersion = 2;
     48         return;
     49     }
     50     if (MTLFeatureSet_OSX_GPUFamily1_v1 == featureSet) {
     51         fPlatform = Platform::kMac;
     52         fFamilyGroup = 1;
     53         fVersion = 1;
     54         return;
     55     }
     56 #endif
     57 
     58     // iOS Family group 3
     59 #ifdef SK_BUILD_FOR_IOS
     60     if (MTLFeatureSet_iOS_GPUFamily3_v2 == featureSet) {
     61         fPlatform = Platform::kIOS;
     62         fFamilyGroup = 3;
     63         fVersion = 2;
     64         return;
     65     }
     66     if (MTLFeatureSet_iOS_GPUFamily3_v1 == featureSet) {
     67         fPlatform = Platform::kIOS;
     68         fFamilyGroup = 3;
     69         fVersion = 1;
     70         return;
     71     }
     72 
     73     // iOS Family group 2
     74     if (MTLFeatureSet_iOS_GPUFamily2_v3 == featureSet) {
     75         fPlatform = Platform::kIOS;
     76         fFamilyGroup = 2;
     77         fVersion = 3;
     78         return;
     79     }
     80     if (MTLFeatureSet_iOS_GPUFamily2_v2 == featureSet) {
     81         fPlatform = Platform::kIOS;
     82         fFamilyGroup = 2;
     83         fVersion = 2;
     84         return;
     85     }
     86     if (MTLFeatureSet_iOS_GPUFamily2_v1 == featureSet) {
     87         fPlatform = Platform::kIOS;
     88         fFamilyGroup = 2;
     89         fVersion = 1;
     90         return;
     91     }
     92 
     93     // iOS Family group 1
     94     if (MTLFeatureSet_iOS_GPUFamily1_v3 == featureSet) {
     95         fPlatform = Platform::kIOS;
     96         fFamilyGroup = 1;
     97         fVersion = 3;
     98         return;
     99     }
    100     if (MTLFeatureSet_iOS_GPUFamily1_v2 == featureSet) {
    101         fPlatform = Platform::kIOS;
    102         fFamilyGroup = 1;
    103         fVersion = 2;
    104         return;
    105     }
    106     if (MTLFeatureSet_iOS_GPUFamily1_v1 == featureSet) {
    107         fPlatform = Platform::kIOS;
    108         fFamilyGroup = 1;
    109         fVersion = 1;
    110         return;
    111     }
    112 #endif
    113     // No supported feature sets were found
    114     SK_ABORT("Requested an unsupported feature set");
    115 }
    116 
    117 bool GrMtlCaps::canCopyAsBlit(GrPixelConfig dstConfig, int dstSampleCount,
    118                               GrSurfaceOrigin dstOrigin,
    119                               GrPixelConfig srcConfig, int srcSampleCount,
    120                               GrSurfaceOrigin srcOrigin,
    121                               const SkIRect& srcRect, const SkIPoint& dstPoint,
    122                               bool areDstSrcSameObj) const {
    123     if (dstConfig != srcConfig) {
    124         return false;
    125     }
    126     if ((dstSampleCount > 1 || srcSampleCount > 1) && (dstSampleCount != srcSampleCount)) {
    127         return false;
    128     }
    129     if (dstOrigin != srcOrigin) {
    130         return false;
    131     }
    132     if (areDstSrcSameObj) {
    133         SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.x(), dstPoint.y(),
    134                                             srcRect.width(), srcRect.height());
    135         if (dstRect.intersect(srcRect)) {
    136             return false;
    137         }
    138     }
    139     return true;
    140 }
    141 
    142 bool GrMtlCaps::canCopyAsDraw(GrPixelConfig dstConfig, bool dstIsRenderable,
    143                               GrPixelConfig srcConfig, bool srcIsTextureable) const {
    144     // TODO: Make copySurfaceAsDraw handle the swizzle
    145     if (this->shaderCaps()->configOutputSwizzle(srcConfig) !=
    146         this->shaderCaps()->configOutputSwizzle(dstConfig)) {
    147         return false;
    148     }
    149 
    150     if (!dstIsRenderable || !srcIsTextureable) {
    151         return false;
    152     }
    153     return true;
    154 }
    155 
    156 bool GrMtlCaps::canCopyAsDrawThenBlit(GrPixelConfig dstConfig, GrPixelConfig srcConfig,
    157                                       bool srcIsTextureable) const {
    158     // TODO: Make copySurfaceAsDraw handle the swizzle
    159     if (this->shaderCaps()->configOutputSwizzle(srcConfig) !=
    160         this->shaderCaps()->configOutputSwizzle(dstConfig)) {
    161         return false;
    162     }
    163     if (!srcIsTextureable) {
    164         return false;
    165     }
    166     return true;
    167 }
    168 
    169 bool GrMtlCaps::onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
    170                                  const SkIRect& srcRect, const SkIPoint& dstPoint) const {
    171     GrSurfaceOrigin dstOrigin = dst->origin();
    172     GrSurfaceOrigin srcOrigin = src->origin();
    173 
    174     int dstSampleCnt = 0;
    175     int srcSampleCnt = 0;
    176     if (const GrRenderTargetProxy* rtProxy = dst->asRenderTargetProxy()) {
    177         dstSampleCnt = rtProxy->numColorSamples();
    178     }
    179     if (const GrRenderTargetProxy* rtProxy = src->asRenderTargetProxy()) {
    180         srcSampleCnt = rtProxy->numColorSamples();
    181     }
    182     SkASSERT((dstSampleCnt > 0) == SkToBool(dst->asRenderTargetProxy()));
    183     SkASSERT((srcSampleCnt > 0) == SkToBool(src->asRenderTargetProxy()));
    184 
    185     return this->canCopyAsBlit(dst->config(), dstSampleCnt, dstOrigin,
    186                                src->config(), srcSampleCnt, srcOrigin,
    187                                srcRect, dstPoint, dst == src) ||
    188            this->canCopyAsDraw(dst->config(), SkToBool(dst->asRenderTargetProxy()),
    189                                src->config(), SkToBool(src->asTextureProxy())) ||
    190            this->canCopyAsDrawThenBlit(dst->config(), src->config(),
    191                                        SkToBool(src->asTextureProxy()));
    192 }
    193 
    194 void GrMtlCaps::initGrCaps(const id<MTLDevice> device) {
    195     // Max vertex attribs is the same on all devices
    196     fMaxVertexAttributes = 31;
    197 
    198     // Metal does not support scissor + clear
    199     fPerformPartialClearsAsDraws = true;
    200 
    201     // RenderTarget and Texture size
    202     if (this->isMac()) {
    203         fMaxRenderTargetSize = 16384;
    204     } else {
    205         if (3 == fFamilyGroup) {
    206             fMaxRenderTargetSize = 16384;
    207         } else {
    208             // Family group 1 and 2 support 8192 for version 2 and above, 4096 for v1
    209             if (1 == fVersion) {
    210                 fMaxRenderTargetSize = 4096;
    211             } else {
    212                 fMaxRenderTargetSize = 8192;
    213             }
    214         }
    215     }
    216     fMaxPreferredRenderTargetSize = fMaxRenderTargetSize;
    217     fMaxTextureSize = fMaxRenderTargetSize;
    218 
    219     // Init sample counts. All devices support 1 (i.e. 0 in skia).
    220     fSampleCounts.push_back(1);
    221     for (auto sampleCnt : {2, 4, 8}) {
    222         if ([device supportsTextureSampleCount:sampleCnt]) {
    223             fSampleCounts.push_back(sampleCnt);
    224         }
    225     }
    226 
    227     // Clamp to border is supported on Mac 10.12 and higher (gpu family.version >= 1.2). It is not
    228     // supported on iOS.
    229     if (this->isMac()) {
    230         if (fFamilyGroup == 1 && fVersion < 2) {
    231             fClampToBorderSupport = false;
    232         }
    233     } else {
    234         fClampToBorderSupport = false;
    235     }
    236 
    237     // Starting with the assumption that there isn't a reason to not map small buffers.
    238     fBufferMapThreshold = 0;
    239 
    240     // Buffers are always fully mapped.
    241     fMapBufferFlags = kCanMap_MapFlag;
    242 
    243     fOversizedStencilSupport = true;
    244 
    245     fSRGBSupport = true;   // always available in Metal
    246     fSRGBWriteControl = false;
    247     fMipMapSupport = true;   // always available in Metal
    248     fNPOTTextureTileSupport = true;  // always available in Metal
    249     fDiscardRenderTargetSupport = true;
    250 
    251     fReuseScratchTextures = true; // Assuming this okay
    252 
    253     fTextureBarrierSupport = false; // Need to figure out if we can do this
    254 
    255     fSampleLocationsSupport = false;
    256     fMultisampleDisableSupport = false;
    257 
    258     if (this->isMac() || 3 == fFamilyGroup) {
    259         fInstanceAttribSupport = true;
    260     }
    261 
    262     fUsesMixedSamples = false;
    263     fGpuTracingSupport = false;
    264 
    265     fFenceSyncSupport = true;   // always available in Metal
    266     fCrossContextTextureSupport = false;
    267     fHalfFloatVertexAttributeSupport = true;
    268 }
    269 
    270 
    271 int GrMtlCaps::maxRenderTargetSampleCount(GrPixelConfig config) const {
    272     if (fConfigTable[config].fFlags & ConfigInfo::kMSAA_Flag) {
    273         return fSampleCounts[fSampleCounts.count() - 1];
    274     } else if (fConfigTable[config].fFlags & ConfigInfo::kRenderable_Flag) {
    275         return 1;
    276     }
    277     return 0;
    278 }
    279 
    280 int GrMtlCaps::getRenderTargetSampleCount(int requestedCount, GrPixelConfig config) const {
    281     requestedCount = SkTMax(requestedCount, 1);
    282     if (fConfigTable[config].fFlags & ConfigInfo::kMSAA_Flag) {
    283         int count = fSampleCounts.count();
    284         for (int i = 0; i < count; ++i) {
    285             if (fSampleCounts[i] >= requestedCount) {
    286                 return fSampleCounts[i];
    287             }
    288         }
    289     } else if (fConfigTable[config].fFlags & ConfigInfo::kRenderable_Flag) {
    290         return 1 == requestedCount ? 1 : 0;
    291     }
    292     return 0;
    293 }
    294 
    295 void GrMtlCaps::initShaderCaps() {
    296     GrShaderCaps* shaderCaps = fShaderCaps.get();
    297 
    298     // fConfigOutputSwizzle will default to RGBA so we only need to set it for alpha only config.
    299     for (int i = 0; i < kGrPixelConfigCnt; ++i) {
    300         GrPixelConfig config = static_cast<GrPixelConfig>(i);
    301         if (GrPixelConfigIsAlphaOnly(config)) {
    302             shaderCaps->fConfigTextureSwizzle[i] = GrSwizzle::RRRR();
    303             shaderCaps->fConfigOutputSwizzle[i] = GrSwizzle::AAAA();
    304         } else {
    305             if (kGray_8_GrPixelConfig == config) {
    306                 shaderCaps->fConfigTextureSwizzle[i] = GrSwizzle::RRRA();
    307             } else if (kRGB_888X_GrPixelConfig == config) {
    308                 shaderCaps->fConfigTextureSwizzle[i] = GrSwizzle::RGB1();
    309             } else {
    310                 shaderCaps->fConfigTextureSwizzle[i] = GrSwizzle::RGBA();
    311             }
    312         }
    313     }
    314 
    315     // Setting this true with the assumption that this cap will eventually mean we support varying
    316     // precisions and not just via modifiers.
    317     shaderCaps->fUsesPrecisionModifiers = true;
    318     shaderCaps->fFlatInterpolationSupport = true;
    319     // We haven't yet tested that using flat attributes perform well.
    320     shaderCaps->fPreferFlatInterpolation = true;
    321 
    322     shaderCaps->fShaderDerivativeSupport = true;
    323     shaderCaps->fGeometryShaderSupport = false;
    324 
    325     if ((this->isMac() && fVersion >= 2) ||
    326         (this->isIOS() && ((1 == fFamilyGroup && 4 == fVersion) ||
    327                            (2 == fFamilyGroup && 4 == fVersion) ||
    328                            (3 == fFamilyGroup && 3 == fVersion)))) {
    329         shaderCaps->fDualSourceBlendingSupport = true;
    330     }
    331 
    332     // TODO: Re-enable this once skbug:8720 is fixed. Will also need to remove asserts in
    333     // GrMtlPipelineStateBuilder which assert we aren't using this feature.
    334 #if 0
    335     if (this->isIOS()) {
    336         shaderCaps->fFBFetchSupport = true;
    337         shaderCaps->fFBFetchNeedsCustomOutput = true; // ??
    338         shaderCaps->fFBFetchColorName = ""; // Somehow add [[color(0)]] to arguments to frag shader
    339     }
    340 #endif
    341     shaderCaps->fDstReadInShaderSupport = shaderCaps->fFBFetchSupport;
    342 
    343     shaderCaps->fIntegerSupport = true;
    344     shaderCaps->fVertexIDSupport = false;
    345     shaderCaps->fImageLoadStoreSupport = false;
    346 
    347     // Metal uses IEEE float and half floats so assuming those values here.
    348     shaderCaps->fFloatIs32Bits = true;
    349     shaderCaps->fHalfIs32Bits = false;
    350 
    351     // Metal supports unsigned integers.
    352     shaderCaps->fUnsignedSupport = true;
    353 
    354     shaderCaps->fMaxFragmentSamplers = 16;
    355 }
    356 
    357 void GrMtlCaps::initConfigTable() {
    358     ConfigInfo* info;
    359     // Alpha_8 uses R8Unorm
    360     info = &fConfigTable[kAlpha_8_GrPixelConfig];
    361     info->fFlags = ConfigInfo::kAllFlags;
    362 
    363     // Gray_8 uses R8Unorm
    364     info = &fConfigTable[kGray_8_GrPixelConfig];
    365     info->fFlags = ConfigInfo::kAllFlags;
    366 
    367     // RGB_565 uses B5G6R5Unorm, even though written opposite this format packs how we want
    368     info = &fConfigTable[kRGB_565_GrPixelConfig];
    369     if (this->isMac()) {
    370         info->fFlags = 0;
    371     } else {
    372         info->fFlags = ConfigInfo::kAllFlags;
    373     }
    374 
    375     // RGBA_4444 uses ABGR4Unorm
    376     info = &fConfigTable[kRGBA_4444_GrPixelConfig];
    377     if (this->isMac()) {
    378         info->fFlags = 0;
    379     } else {
    380         info->fFlags = ConfigInfo::kAllFlags;
    381     }
    382 
    383     // RGBA_8888 uses RGBA8Unorm
    384     info = &fConfigTable[kRGBA_8888_GrPixelConfig];
    385     info->fFlags = ConfigInfo::kAllFlags;
    386 
    387     // RGB_888X uses RGBA8Unorm and we will swizzle the 1
    388     info = &fConfigTable[kRGB_888X_GrPixelConfig];
    389     info->fFlags = ConfigInfo::kTextureable_Flag;
    390 
    391     // BGRA_8888 uses BGRA8Unorm
    392     info = &fConfigTable[kBGRA_8888_GrPixelConfig];
    393     info->fFlags = ConfigInfo::kAllFlags;
    394 
    395     // SRGBA_8888 uses RGBA8Unorm_sRGB
    396     info = &fConfigTable[kSRGBA_8888_GrPixelConfig];
    397     info->fFlags = ConfigInfo::kAllFlags;
    398 
    399     // SBGRA_8888 uses BGRA8Unorm_sRGB
    400     info = &fConfigTable[kSBGRA_8888_GrPixelConfig];
    401     info->fFlags = ConfigInfo::kAllFlags;
    402 
    403     // RGBA_float uses RGBA32Float
    404     info = &fConfigTable[kRGBA_float_GrPixelConfig];
    405     if (this->isMac()) {
    406         info->fFlags = ConfigInfo::kAllFlags;
    407     } else {
    408         info->fFlags = 0;
    409     }
    410 
    411     // RG_float uses RG32Float
    412     info = &fConfigTable[kRG_float_GrPixelConfig];
    413     if (this->isMac()) {
    414         info->fFlags = ConfigInfo::kAllFlags;
    415     } else {
    416         info->fFlags = ConfigInfo::kRenderable_Flag;
    417     }
    418 
    419     // Alpha_half uses R16Float
    420     info = &fConfigTable[kAlpha_half_GrPixelConfig];
    421     info->fFlags = ConfigInfo::kAllFlags;
    422 
    423     // RGBA_half uses RGBA16Float
    424     info = &fConfigTable[kRGBA_half_GrPixelConfig];
    425     info->fFlags = ConfigInfo::kAllFlags;
    426 
    427     info = &fConfigTable[kRGBA_half_Clamped_GrPixelConfig];
    428     info->fFlags = ConfigInfo::kAllFlags;
    429 }
    430 
    431 void GrMtlCaps::initStencilFormat(id<MTLDevice> physDev) {
    432     fPreferredStencilFormat = StencilFormat{ MTLPixelFormatStencil8, 8, 8, true };
    433 }
    434 
    435 GrPixelConfig validate_sized_format(GrMTLPixelFormat grFormat, SkColorType ct) {
    436     MTLPixelFormat format = static_cast<MTLPixelFormat>(grFormat);
    437     switch (ct) {
    438         case kUnknown_SkColorType:
    439             return kUnknown_GrPixelConfig;
    440         case kAlpha_8_SkColorType:
    441             if (MTLPixelFormatA8Unorm == format) {
    442                 return kAlpha_8_as_Alpha_GrPixelConfig;
    443             } else if (MTLPixelFormatR8Unorm == format) {
    444                 return kAlpha_8_as_Red_GrPixelConfig;
    445             }
    446             break;
    447 #ifdef SK_BUILD_FOR_MAC
    448         case kRGB_565_SkColorType:
    449         case kARGB_4444_SkColorType:
    450             return kUnknown_GrPixelConfig;
    451             break;
    452 #else
    453         case kRGB_565_SkColorType:
    454             if (MTLPixelFormatB5G6R5Unorm == format) {
    455                 return kRGB_565_GrPixelConfig;
    456             }
    457             break;
    458         case kARGB_4444_SkColorType:
    459             if (MTLPixelFormatABGR4Unorm == format) {
    460                 return kRGBA_4444_GrPixelConfig;
    461             }
    462             break;
    463 #endif
    464         case kRGBA_8888_SkColorType:
    465             if (MTLPixelFormatRGBA8Unorm == format) {
    466                 return kRGBA_8888_GrPixelConfig;
    467             } else if (MTLPixelFormatRGBA8Unorm_sRGB == format) {
    468                 return kSRGBA_8888_GrPixelConfig;
    469             }
    470             break;
    471         case kRGB_888x_SkColorType:
    472             if (MTLPixelFormatRGBA8Unorm == format) {
    473                 return kRGB_888X_GrPixelConfig;
    474             }
    475             break;
    476         case kBGRA_8888_SkColorType:
    477             if (MTLPixelFormatBGRA8Unorm == format) {
    478                 return kBGRA_8888_GrPixelConfig;
    479             } else if (MTLPixelFormatBGRA8Unorm_sRGB == format) {
    480                 return kSBGRA_8888_GrPixelConfig;
    481             }
    482             break;
    483         case kRGBA_1010102_SkColorType:
    484             if (MTLPixelFormatRGB10A2Unorm == format) {
    485                 return kRGBA_1010102_GrPixelConfig;
    486             }
    487             break;
    488         case kRGB_101010x_SkColorType:
    489             break;
    490         case kGray_8_SkColorType:
    491             if (MTLPixelFormatR8Unorm == format) {
    492                 return kGray_8_as_Red_GrPixelConfig;
    493             }
    494             break;
    495         case kRGBA_F16Norm_SkColorType:
    496             if (MTLPixelFormatRGBA16Float == format) {
    497                 return kRGBA_half_Clamped_GrPixelConfig;
    498             }
    499             break;
    500         case kRGBA_F16_SkColorType:
    501             if (MTLPixelFormatRGBA16Float == format) {
    502                 return kRGBA_half_GrPixelConfig;
    503             }
    504             break;
    505         case kRGBA_F32_SkColorType:
    506             if (MTLPixelFormatR32Float == format) {
    507                 return kRGBA_float_GrPixelConfig;
    508             }
    509             break;
    510     }
    511 
    512     return kUnknown_GrPixelConfig;
    513 }
    514 
    515 GrPixelConfig GrMtlCaps::validateBackendRenderTarget(const GrBackendRenderTarget& rt,
    516                                                      SkColorType ct) const {
    517     GrMtlTextureInfo fbInfo;
    518     if (!rt.getMtlTextureInfo(&fbInfo)) {
    519         return kUnknown_GrPixelConfig;
    520     }
    521 
    522     id<MTLTexture> texture = (__bridge id<MTLTexture>)fbInfo.fTexture;
    523     return validate_sized_format(texture.pixelFormat, ct);
    524 }
    525 
    526 GrPixelConfig GrMtlCaps::getConfigFromBackendFormat(const GrBackendFormat& format,
    527                                                     SkColorType ct) const {
    528     const GrMTLPixelFormat* mtlFormat = format.getMtlFormat();
    529     if (!mtlFormat) {
    530         return kUnknown_GrPixelConfig;
    531     }
    532     return validate_sized_format(*mtlFormat, ct);
    533 }
    534 
    535 static GrPixelConfig get_yuva_config(GrMTLPixelFormat grFormat) {
    536     MTLPixelFormat format = static_cast<MTLPixelFormat>(grFormat);
    537 
    538     switch (format) {
    539         case MTLPixelFormatA8Unorm:
    540             return kAlpha_8_as_Alpha_GrPixelConfig;
    541             break;
    542         case MTLPixelFormatR8Unorm:
    543             return kAlpha_8_as_Red_GrPixelConfig;
    544             break;
    545         // TODO: Add RG_88 format here
    546         case MTLPixelFormatRGBA8Unorm:
    547             return kRGBA_8888_GrPixelConfig;
    548             break;
    549         case MTLPixelFormatBGRA8Unorm:
    550             return kBGRA_8888_GrPixelConfig;
    551             break;
    552         default:
    553             return kUnknown_GrPixelConfig;
    554             break;
    555     }
    556 }
    557 
    558 GrPixelConfig GrMtlCaps::getYUVAConfigFromBackendFormat(const GrBackendFormat& format) const {
    559     const GrMTLPixelFormat* mtlFormat = format.getMtlFormat();
    560     if (!mtlFormat) {
    561         return kUnknown_GrPixelConfig;
    562     }
    563     return get_yuva_config(*mtlFormat);
    564 }
    565 
    566 GrBackendFormat GrMtlCaps::getBackendFormatFromGrColorType(GrColorType ct,
    567                                                            GrSRGBEncoded srgbEncoded) const {
    568     GrPixelConfig config = GrColorTypeToPixelConfig(ct, srgbEncoded);
    569     if (config == kUnknown_GrPixelConfig) {
    570         return GrBackendFormat();
    571     }
    572     MTLPixelFormat format;
    573     if (!GrPixelConfigToMTLFormat(config, &format)) {
    574         return GrBackendFormat();
    575     }
    576     return GrBackendFormat::MakeMtl(format);
    577 }
    578 
    579