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