1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2021 Google LLC
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "experimental/graphite/src/mtl/MtlCaps.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "experimental/graphite/include/TextureInfo.h"
11cb93a386Sopenharmony_ci#include "experimental/graphite/include/mtl/MtlTypes.h"
12cb93a386Sopenharmony_ci#include "experimental/graphite/src/mtl/MtlUtils.h"
13cb93a386Sopenharmony_ci
14cb93a386Sopenharmony_cinamespace skgpu::mtl {
15cb93a386Sopenharmony_ci
16cb93a386Sopenharmony_ciCaps::Caps(const id<MTLDevice> device)
17cb93a386Sopenharmony_ci        : skgpu::Caps() {
18cb93a386Sopenharmony_ci    // TODO: allocate shadercaps
19cb93a386Sopenharmony_ci
20cb93a386Sopenharmony_ci    this->initGPUFamily(device);
21cb93a386Sopenharmony_ci    this->initCaps(device);
22cb93a386Sopenharmony_ci    this->initShaderCaps();
23cb93a386Sopenharmony_ci
24cb93a386Sopenharmony_ci    this->initFormatTable();
25cb93a386Sopenharmony_ci
26cb93a386Sopenharmony_ci    // Metal-specific caps
27cb93a386Sopenharmony_ci}
28cb93a386Sopenharmony_ci
29cb93a386Sopenharmony_ci// translates from older MTLFeatureSet interface to MTLGPUFamily interface
30cb93a386Sopenharmony_cibool Caps::GetGPUFamilyFromFeatureSet(id<MTLDevice> device, GPUFamily* gpuFamily, int* group) {
31cb93a386Sopenharmony_ci#if defined(SK_BUILD_FOR_MAC)
32cb93a386Sopenharmony_ci    // Apple Silicon is only available in later OSes
33cb93a386Sopenharmony_ci    *gpuFamily = GPUFamily::kMac;
34cb93a386Sopenharmony_ci    // Mac OSX 14
35cb93a386Sopenharmony_ci    if (@available(macOS 10.14, *)) {
36cb93a386Sopenharmony_ci        if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily2_v1]) {
37cb93a386Sopenharmony_ci            *group = 2;
38cb93a386Sopenharmony_ci            return true;
39cb93a386Sopenharmony_ci        }
40cb93a386Sopenharmony_ci        if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v4]) {
41cb93a386Sopenharmony_ci            *group = 1;
42cb93a386Sopenharmony_ci            return true;
43cb93a386Sopenharmony_ci        }
44cb93a386Sopenharmony_ci    }
45cb93a386Sopenharmony_ci    // Mac OSX 13
46cb93a386Sopenharmony_ci    if (@available(macOS 10.13, *)) {
47cb93a386Sopenharmony_ci        if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v3]) {
48cb93a386Sopenharmony_ci            *group = 1;
49cb93a386Sopenharmony_ci            return true;
50cb93a386Sopenharmony_ci        }
51cb93a386Sopenharmony_ci    }
52cb93a386Sopenharmony_ci    // Mac OSX 12
53cb93a386Sopenharmony_ci    if (@available(macOS 10.12, *)) {
54cb93a386Sopenharmony_ci        if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v2]) {
55cb93a386Sopenharmony_ci            *group = 1;
56cb93a386Sopenharmony_ci            return true;
57cb93a386Sopenharmony_ci        }
58cb93a386Sopenharmony_ci    }
59cb93a386Sopenharmony_ci    // Mac OSX 11
60cb93a386Sopenharmony_ci    if (@available(macOS 10.11, *)) {
61cb93a386Sopenharmony_ci        if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v1]) {
62cb93a386Sopenharmony_ci            *group = 1;
63cb93a386Sopenharmony_ci            return true;
64cb93a386Sopenharmony_ci        }
65cb93a386Sopenharmony_ci    }
66cb93a386Sopenharmony_ci#elif defined(SK_BUILD_FOR_IOS)
67cb93a386Sopenharmony_ci    // TODO: support tvOS
68cb93a386Sopenharmony_ci   *gpuFamily = GPUFamily::kApple;
69cb93a386Sopenharmony_ci    // iOS 12
70cb93a386Sopenharmony_ci    if (@available(iOS 12.0, *)) {
71cb93a386Sopenharmony_ci        if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily5_v1]) {
72cb93a386Sopenharmony_ci            *group = 5;
73cb93a386Sopenharmony_ci            return true;
74cb93a386Sopenharmony_ci        }
75cb93a386Sopenharmony_ci        if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily4_v2]) {
76cb93a386Sopenharmony_ci            *group = 4;
77cb93a386Sopenharmony_ci            return true;
78cb93a386Sopenharmony_ci        }
79cb93a386Sopenharmony_ci        if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v4]) {
80cb93a386Sopenharmony_ci            *group = 3;
81cb93a386Sopenharmony_ci            return true;
82cb93a386Sopenharmony_ci        }
83cb93a386Sopenharmony_ci        if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily2_v5]) {
84cb93a386Sopenharmony_ci            *group = 2;
85cb93a386Sopenharmony_ci            return true;
86cb93a386Sopenharmony_ci        }
87cb93a386Sopenharmony_ci        if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily1_v5]) {
88cb93a386Sopenharmony_ci            *group = 1;
89cb93a386Sopenharmony_ci            return true;
90cb93a386Sopenharmony_ci        }
91cb93a386Sopenharmony_ci    }
92cb93a386Sopenharmony_ci    // iOS 11
93cb93a386Sopenharmony_ci    if (@available(iOS 11.0, *)) {
94cb93a386Sopenharmony_ci        if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily4_v1]) {
95cb93a386Sopenharmony_ci            *group = 4;
96cb93a386Sopenharmony_ci            return true;
97cb93a386Sopenharmony_ci        }
98cb93a386Sopenharmony_ci        if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v3]) {
99cb93a386Sopenharmony_ci            *group = 3;
100cb93a386Sopenharmony_ci            return true;
101cb93a386Sopenharmony_ci        }
102cb93a386Sopenharmony_ci        if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily2_v4]) {
103cb93a386Sopenharmony_ci            *group = 2;
104cb93a386Sopenharmony_ci            return true;
105cb93a386Sopenharmony_ci        }
106cb93a386Sopenharmony_ci        if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily1_v4]) {
107cb93a386Sopenharmony_ci            *group = 1;
108cb93a386Sopenharmony_ci            return true;
109cb93a386Sopenharmony_ci        }
110cb93a386Sopenharmony_ci    }
111cb93a386Sopenharmony_ci    // iOS 10
112cb93a386Sopenharmony_ci    if (@available(iOS 10.0, *)) {
113cb93a386Sopenharmony_ci        if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v2]) {
114cb93a386Sopenharmony_ci            *group = 3;
115cb93a386Sopenharmony_ci            return true;
116cb93a386Sopenharmony_ci        }
117cb93a386Sopenharmony_ci        if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily2_v3]) {
118cb93a386Sopenharmony_ci            *group = 2;
119cb93a386Sopenharmony_ci            return true;
120cb93a386Sopenharmony_ci        }
121cb93a386Sopenharmony_ci        if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily1_v3]) {
122cb93a386Sopenharmony_ci            *group = 1;
123cb93a386Sopenharmony_ci            return true;
124cb93a386Sopenharmony_ci        }
125cb93a386Sopenharmony_ci    }
126cb93a386Sopenharmony_ci    // We don't support earlier OSes
127cb93a386Sopenharmony_ci#endif
128cb93a386Sopenharmony_ci
129cb93a386Sopenharmony_ci    // No supported GPU families were found
130cb93a386Sopenharmony_ci    return false;
131cb93a386Sopenharmony_ci}
132cb93a386Sopenharmony_ci
133cb93a386Sopenharmony_cibool Caps::GetGPUFamily(id<MTLDevice> device, GPUFamily* gpuFamily, int* group) {
134cb93a386Sopenharmony_ci#if GR_METAL_SDK_VERSION >= 220
135cb93a386Sopenharmony_ci    if (@available(macOS 10.15, iOS 13.0, tvOS 13.0, *)) {
136cb93a386Sopenharmony_ci        // Apple Silicon
137cb93a386Sopenharmony_ci#if GR_METAL_SDK_VERSION >= 230
138cb93a386Sopenharmony_ci        if ([device supportsFamily:MTLGPUFamilyApple7]) {
139cb93a386Sopenharmony_ci            *gpuFamily = GPUFamily::kApple;
140cb93a386Sopenharmony_ci            *group = 7;
141cb93a386Sopenharmony_ci            return true;
142cb93a386Sopenharmony_ci        }
143cb93a386Sopenharmony_ci#endif
144cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_IOS
145cb93a386Sopenharmony_ci        if ([device supportsFamily:MTLGPUFamilyApple6]) {
146cb93a386Sopenharmony_ci            *gpuFamily = GPUFamily::kApple;
147cb93a386Sopenharmony_ci            *group = 6;
148cb93a386Sopenharmony_ci            return true;
149cb93a386Sopenharmony_ci        }
150cb93a386Sopenharmony_ci        if ([device supportsFamily:MTLGPUFamilyApple5]) {
151cb93a386Sopenharmony_ci            *gpuFamily = GPUFamily::kApple;
152cb93a386Sopenharmony_ci            *group = 5;
153cb93a386Sopenharmony_ci            return true;
154cb93a386Sopenharmony_ci        }
155cb93a386Sopenharmony_ci        if ([device supportsFamily:MTLGPUFamilyApple4]) {
156cb93a386Sopenharmony_ci            *gpuFamily = GPUFamily::kApple;
157cb93a386Sopenharmony_ci            *group = 4;
158cb93a386Sopenharmony_ci            return true;
159cb93a386Sopenharmony_ci        }
160cb93a386Sopenharmony_ci        if ([device supportsFamily:MTLGPUFamilyApple3]) {
161cb93a386Sopenharmony_ci            *gpuFamily = GPUFamily::kApple;
162cb93a386Sopenharmony_ci            *group = 3;
163cb93a386Sopenharmony_ci            return true;
164cb93a386Sopenharmony_ci        }
165cb93a386Sopenharmony_ci        if ([device supportsFamily:MTLGPUFamilyApple2]) {
166cb93a386Sopenharmony_ci            *gpuFamily = GPUFamily::kApple;
167cb93a386Sopenharmony_ci            *group = 2;
168cb93a386Sopenharmony_ci            return true;
169cb93a386Sopenharmony_ci        }
170cb93a386Sopenharmony_ci        if ([device supportsFamily:MTLGPUFamilyApple1]) {
171cb93a386Sopenharmony_ci            *gpuFamily = GPUFamily::kApple;
172cb93a386Sopenharmony_ci            *group = 1;
173cb93a386Sopenharmony_ci            return true;
174cb93a386Sopenharmony_ci        }
175cb93a386Sopenharmony_ci#endif
176cb93a386Sopenharmony_ci
177cb93a386Sopenharmony_ci        // Older Macs
178cb93a386Sopenharmony_ci        // At the moment MacCatalyst families have the same features as Mac,
179cb93a386Sopenharmony_ci        // so we treat them the same
180cb93a386Sopenharmony_ci        if ([device supportsFamily:MTLGPUFamilyMac2] ||
181cb93a386Sopenharmony_ci            [device supportsFamily:MTLGPUFamilyMacCatalyst2]) {
182cb93a386Sopenharmony_ci            *gpuFamily = GPUFamily::kMac;
183cb93a386Sopenharmony_ci            *group = 2;
184cb93a386Sopenharmony_ci            return true;
185cb93a386Sopenharmony_ci        }
186cb93a386Sopenharmony_ci        if ([device supportsFamily:MTLGPUFamilyMac1] ||
187cb93a386Sopenharmony_ci            [device supportsFamily:MTLGPUFamilyMacCatalyst1]) {
188cb93a386Sopenharmony_ci            *gpuFamily = GPUFamily::kMac;
189cb93a386Sopenharmony_ci            *group = 1;
190cb93a386Sopenharmony_ci            return true;
191cb93a386Sopenharmony_ci        }
192cb93a386Sopenharmony_ci    }
193cb93a386Sopenharmony_ci#endif
194cb93a386Sopenharmony_ci
195cb93a386Sopenharmony_ci    // No supported GPU families were found
196cb93a386Sopenharmony_ci    return false;
197cb93a386Sopenharmony_ci}
198cb93a386Sopenharmony_ci
199cb93a386Sopenharmony_civoid Caps::initGPUFamily(id<MTLDevice> device) {
200cb93a386Sopenharmony_ci    if (!GetGPUFamily(device, &fGPUFamily, &fFamilyGroup) &&
201cb93a386Sopenharmony_ci        !GetGPUFamilyFromFeatureSet(device, &fGPUFamily, &fFamilyGroup)) {
202cb93a386Sopenharmony_ci        // We don't know what this is, fall back to minimum defaults
203cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_MAC
204cb93a386Sopenharmony_ci        fGPUFamily = GPUFamily::kMac;
205cb93a386Sopenharmony_ci        fFamilyGroup = 1;
206cb93a386Sopenharmony_ci#else
207cb93a386Sopenharmony_ci        fGPUFamily = GPUFamily::kApple;
208cb93a386Sopenharmony_ci        fFamilyGroup = 1;
209cb93a386Sopenharmony_ci#endif
210cb93a386Sopenharmony_ci    }
211cb93a386Sopenharmony_ci}
212cb93a386Sopenharmony_ci
213cb93a386Sopenharmony_civoid Caps::initCaps(const id<MTLDevice> device) {
214cb93a386Sopenharmony_ci    // TODO
215cb93a386Sopenharmony_ci}
216cb93a386Sopenharmony_ci
217cb93a386Sopenharmony_civoid Caps::initShaderCaps() {
218cb93a386Sopenharmony_ci    // TODO
219cb93a386Sopenharmony_ci}
220cb93a386Sopenharmony_ci
221cb93a386Sopenharmony_civoid Caps::initFormatTable() {
222cb93a386Sopenharmony_ci    // TODO
223cb93a386Sopenharmony_ci}
224cb93a386Sopenharmony_ci
225cb93a386Sopenharmony_ciskgpu::TextureInfo Caps::getDefaultSampledTextureInfo(SkColorType colorType,
226cb93a386Sopenharmony_ci                                                      uint32_t levelCount,
227cb93a386Sopenharmony_ci                                                      Protected,
228cb93a386Sopenharmony_ci                                                      Renderable renderable) const {
229cb93a386Sopenharmony_ci    MTLTextureUsage usage = MTLTextureUsageShaderRead;
230cb93a386Sopenharmony_ci    if (renderable == Renderable::kYes) {
231cb93a386Sopenharmony_ci        usage |= MTLTextureUsageRenderTarget;
232cb93a386Sopenharmony_ci    }
233cb93a386Sopenharmony_ci
234cb93a386Sopenharmony_ci    TextureInfo info;
235cb93a386Sopenharmony_ci    info.fSampleCount = 1;
236cb93a386Sopenharmony_ci    info.fLevelCount = levelCount;
237cb93a386Sopenharmony_ci    info.fFormat = SkColorTypeToFormat(colorType);
238cb93a386Sopenharmony_ci    info.fUsage = usage;
239cb93a386Sopenharmony_ci    info.fStorageMode = MTLStorageModePrivate;
240cb93a386Sopenharmony_ci    info.fFramebufferOnly = false;
241cb93a386Sopenharmony_ci
242cb93a386Sopenharmony_ci    return info;
243cb93a386Sopenharmony_ci}
244cb93a386Sopenharmony_ci
245cb93a386Sopenharmony_ciskgpu::TextureInfo Caps::getDefaultMSAATextureInfo(SkColorType colorType,
246cb93a386Sopenharmony_ci                                                   uint32_t sampleCount,
247cb93a386Sopenharmony_ci                                                   Protected) const {
248cb93a386Sopenharmony_ci    MTLTextureUsage usage = MTLTextureUsageRenderTarget;
249cb93a386Sopenharmony_ci
250cb93a386Sopenharmony_ci    TextureInfo info;
251cb93a386Sopenharmony_ci    info.fSampleCount = sampleCount;
252cb93a386Sopenharmony_ci    info.fLevelCount = 1;
253cb93a386Sopenharmony_ci    info.fFormat = SkColorTypeToFormat(colorType);
254cb93a386Sopenharmony_ci    info.fUsage = usage;
255cb93a386Sopenharmony_ci    info.fStorageMode = MTLStorageModePrivate;
256cb93a386Sopenharmony_ci    info.fFramebufferOnly = false;
257cb93a386Sopenharmony_ci
258cb93a386Sopenharmony_ci    return info;
259cb93a386Sopenharmony_ci}
260cb93a386Sopenharmony_ci
261cb93a386Sopenharmony_ciskgpu::TextureInfo Caps::getDefaultDepthStencilTextureInfo(DepthStencilType depthStencilType,
262cb93a386Sopenharmony_ci                                                           uint32_t sampleCount,
263cb93a386Sopenharmony_ci                                                           Protected) const {
264cb93a386Sopenharmony_ci    TextureInfo info;
265cb93a386Sopenharmony_ci    info.fSampleCount = sampleCount;
266cb93a386Sopenharmony_ci    info.fLevelCount = 1;
267cb93a386Sopenharmony_ci    info.fFormat = DepthStencilTypeToFormat(depthStencilType);
268cb93a386Sopenharmony_ci    info.fUsage = MTLTextureUsageRenderTarget;
269cb93a386Sopenharmony_ci    info.fStorageMode = MTLStorageModePrivate;
270cb93a386Sopenharmony_ci    info.fFramebufferOnly = false;
271cb93a386Sopenharmony_ci
272cb93a386Sopenharmony_ci    return info;
273cb93a386Sopenharmony_ci}
274cb93a386Sopenharmony_ci
275cb93a386Sopenharmony_ci
276cb93a386Sopenharmony_ci
277cb93a386Sopenharmony_ci
278cb93a386Sopenharmony_ci} // namespace skgpu::mtl
279