blob: 2bce74a261199c05ba2c4a1d2b381625acd5f076 [file] [log] [blame]
Greg Danielcebcb842017-07-31 10:45:52 -04001/*
2 * Copyright 2017 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "GrMtlCaps.h"
9
10#include "GrShaderCaps.h"
11
12GrMtlCaps::GrMtlCaps(const GrContextOptions& contextOptions, const id<MTLDevice> device,
13 MTLFeatureSet featureSet)
14 : INHERITED(contextOptions) {
15 fShaderCaps.reset(new GrShaderCaps(contextOptions));
16
17 this->initFeatureSet(featureSet);
18 this->initGrCaps(device);
19 this->initShaderCaps();
20 this->initConfigTable();
21
22 this->applyOptionsOverrides(contextOptions);
23 fShaderCaps->applyOptionsOverrides(contextOptions);
24}
25
26void GrMtlCaps::initFeatureSet(MTLFeatureSet featureSet) {
27 // Mac OSX
28#ifdef SK_BUILD_FOR_MAC
29 if (MTLFeatureSet_OSX_GPUFamily1_v2 == featureSet) {
30 fPlatform = Platform::kMac;
31 fFamilyGroup = 1;
32 fVersion = 2;
33 return;
34 }
35 if (MTLFeatureSet_OSX_GPUFamily1_v1 == featureSet) {
36 fPlatform = Platform::kMac;
37 fFamilyGroup = 1;
38 fVersion = 1;
39 return;
40 }
41#endif
42
43 // iOS Family group 3
44#ifdef SK_BUILD_FOR_IOS
45 if (MTLFeatureSet_iOS_GPUFamily3_v2 == featureSet) {
46 fPlatform = Platform::kIOS;
47 fFamilyGroup = 3;
48 fVersion = 2;
49 return;
50 }
51 if (MTLFeatureSet_iOS_GPUFamily3_v1 == featureSet) {
52 fPlatform = Platform::kIOS;
53 fFamilyGroup = 3;
54 fVersion = 1;
55 return;
56 }
57
58 // iOS Family group 2
59 if (MTLFeatureSet_iOS_GPUFamily2_v3 == featureSet) {
60 fPlatform = Platform::kIOS;
61 fFamilyGroup = 2;
62 fVersion = 3;
63 return;
64 }
65 if (MTLFeatureSet_iOS_GPUFamily2_v2 == featureSet) {
66 fPlatform = Platform::kIOS;
67 fFamilyGroup = 2;
68 fVersion = 2;
69 return;
70 }
71 if (MTLFeatureSet_iOS_GPUFamily2_v1 == featureSet) {
72 fPlatform = Platform::kIOS;
73 fFamilyGroup = 2;
74 fVersion = 1;
75 return;
76 }
77
78 // iOS Family group 1
79 if (MTLFeatureSet_iOS_GPUFamily1_v3 == featureSet) {
80 fPlatform = Platform::kIOS;
81 fFamilyGroup = 1;
82 fVersion = 3;
83 return;
84 }
85 if (MTLFeatureSet_iOS_GPUFamily1_v2 == featureSet) {
86 fPlatform = Platform::kIOS;
87 fFamilyGroup = 1;
88 fVersion = 2;
89 return;
90 }
91 if (MTLFeatureSet_iOS_GPUFamily1_v1 == featureSet) {
92 fPlatform = Platform::kIOS;
93 fFamilyGroup = 1;
94 fVersion = 1;
95 return;
96 }
97#endif
98 // No supported feature sets were found
Ben Wagnerb4aab9a2017-08-16 10:53:04 -040099 SK_ABORT("Requested an unsupported feature set");
Greg Danielcebcb842017-07-31 10:45:52 -0400100}
101
102void GrMtlCaps::initGrCaps(const id<MTLDevice> device) {
103 // Max vertex attribs is the same on all devices
104 fMaxVertexAttributes = 31;
105
106 // RenderTarget and Texture size
107 if (this->isMac()) {
108 fMaxRenderTargetSize = 16384;
109 } else {
110 if (3 == fFamilyGroup) {
111 fMaxRenderTargetSize = 16384;
112 } else {
113 // Family group 1 and 2 support 8192 for version 2 and above, 4096 for v1
114 if (1 == fVersion) {
115 fMaxRenderTargetSize = 4096;
116 } else {
117 fMaxRenderTargetSize = 8192;
118 }
119 }
120 }
121 fMaxTextureSize = fMaxRenderTargetSize;
122
123 // Init sample counts. All devices support 1 (i.e. 0 in skia).
124 fSampleCounts.push(0);
125 for (auto sampleCnt : {2, 4, 8}) {
126 if ([device supportsTextureSampleCount:sampleCnt]) {
127 fSampleCounts.push(sampleCnt);
128 }
129 }
130
131 // Starting with the assumption that there isn't a reason to not map small buffers.
132 fBufferMapThreshold = 0;
133
134 // Buffers are always fully mapped.
135 fMapBufferFlags = kCanMap_MapFlag;
136
137 fOversizedStencilSupport = true;
138
139 // Looks like there is a field called rasterSampleCount labeled as beta in the Metal docs. This
140 // may be what we eventually need here, but it has no description.
141 fSampleShadingSupport = false;
142
143 fSRGBSupport = true; // always available in Metal
144 fSRGBWriteControl = false;
145 fMipMapSupport = true; // always available in Metal
146 fNPOTTextureTileSupport = true; // always available in Metal
147 fDiscardRenderTargetSupport = true;
148
149 fReuseScratchTextures = true; // Assuming this okay
150
151 fTextureBarrierSupport = false; // Need to figure out if we can do this
152
Robert Phillips7f861922018-01-30 13:13:42 +0000153 fSampleLocationsSupport = false;
Greg Danielcebcb842017-07-31 10:45:52 -0400154 fMultisampleDisableSupport = false;
155
156 if (this->isMac() || 3 == fFamilyGroup) {
157 fInstanceAttribSupport = true;
158 }
159
160 fUsesMixedSamples = false;
161 fGpuTracingSupport = false;
162
Greg Danielcebcb842017-07-31 10:45:52 -0400163 fFenceSyncSupport = true; // always available in Metal
164 fCrossContextTextureSupport = false;
Greg Danielcebcb842017-07-31 10:45:52 -0400165}
166
167int GrMtlCaps::getSampleCount(int requestedCount, GrPixelConfig config) const {
168 int count = fSampleCounts.count();
169 SkASSERT(count > 0); // We always add 0 as a valid sample count
170 if (!this->isConfigRenderable(config, true)) {
171 return 0;
172 }
173
174 for (int i = 0; i < count; ++i) {
175 if (fSampleCounts[i] >= requestedCount) {
176 return fSampleCounts[i];
177 }
178 }
179 return fSampleCounts[count-1];
180}
181
182void GrMtlCaps::initShaderCaps() {
183 GrShaderCaps* shaderCaps = fShaderCaps.get();
184
185 // fConfigOutputSwizzle will default to RGBA so we only need to set it for alpha only config.
186 for (int i = 0; i < kGrPixelConfigCnt; ++i) {
187 GrPixelConfig config = static_cast<GrPixelConfig>(i);
188 if (GrPixelConfigIsAlphaOnly(config)) {
189 shaderCaps->fConfigTextureSwizzle[i] = GrSwizzle::RRRR();
190 shaderCaps->fConfigOutputSwizzle[i] = GrSwizzle::AAAA();
191 } else {
192 if (kGray_8_GrPixelConfig == config) {
193 shaderCaps->fConfigTextureSwizzle[i] = GrSwizzle::RRRA();
194 } else {
195 shaderCaps->fConfigTextureSwizzle[i] = GrSwizzle::RGBA();
196 }
197 }
198 }
199
200 // Setting this true with the assumption that this cap will eventually mean we support varying
Brian Salomon41274562017-09-15 09:40:03 -0700201 // precisions and not just via modifiers.
Greg Danielcebcb842017-07-31 10:45:52 -0400202 shaderCaps->fUsesPrecisionModifiers = true;
203 shaderCaps->fFlatInterpolationSupport = true;
Brian Salomon41274562017-09-15 09:40:03 -0700204 // We haven't yet tested that using flat attributes perform well.
205 shaderCaps->fPreferFlatInterpolation = true;
Greg Danielcebcb842017-07-31 10:45:52 -0400206
207 shaderCaps->fShaderDerivativeSupport = true;
208 shaderCaps->fGeometryShaderSupport = false;
209
210 if ((this->isMac() && fVersion >= 2) ||
211 (this->isIOS() && ((1 == fFamilyGroup && 4 == fVersion) ||
212 (2 == fFamilyGroup && 4 == fVersion) ||
213 (3 == fFamilyGroup && 3 == fVersion)))) {
214 shaderCaps->fDualSourceBlendingSupport = true;
215 }
216
217 if (this->isIOS()) {
218 shaderCaps->fFBFetchSupport = true;
219 shaderCaps->fFBFetchNeedsCustomOutput = true; // ??
220 shaderCaps->fFBFetchColorName = ""; // Somehow add [[color(0)]] to arguments to frag shader
221 }
222 shaderCaps->fDstReadInShaderSupport = shaderCaps->fFBFetchSupport;
223
224 shaderCaps->fIntegerSupport = true;
225 shaderCaps->fTexelBufferSupport = false;
226 shaderCaps->fTexelFetchSupport = false;
227 shaderCaps->fVertexIDSupport = false;
228 shaderCaps->fImageLoadStoreSupport = false;
Greg Danielcebcb842017-07-31 10:45:52 -0400229
Chris Dalton47c8ed32017-11-15 18:27:09 -0700230 // Metal uses IEEE float and half floats so assuming those values here.
231 shaderCaps->fFloatIs32Bits = true;
232 shaderCaps->fHalfIs32Bits = false;
Greg Danielcebcb842017-07-31 10:45:52 -0400233
234 shaderCaps->fMaxVertexSamplers =
235 shaderCaps->fMaxFragmentSamplers = 16;
236 // For now just cap at the per stage max. If we hit this limit we can come back to adjust this
237 shaderCaps->fMaxCombinedSamplers = shaderCaps->fMaxVertexSamplers;
238}
239
240void GrMtlCaps::initConfigTable() {
241 ConfigInfo* info;
242 // Alpha_8 uses R8Unorm
243 info = &fConfigTable[kAlpha_8_GrPixelConfig];
244 info->fFlags = ConfigInfo::kAllFlags;
245
246 // Gray_8 uses R8Unorm
247 info = &fConfigTable[kGray_8_GrPixelConfig];
248 info->fFlags = ConfigInfo::kAllFlags;
249
250 // RGB_565 uses B5G6R5Unorm, even though written opposite this format packs how we want
251 info = &fConfigTable[kRGB_565_GrPixelConfig];
252 if (this->isMac()) {
253 info->fFlags = 0;
254 } else {
255 info->fFlags = ConfigInfo::kAllFlags;
256 }
257
258 // RGBA_4444 uses ABGR4Unorm
259 info = &fConfigTable[kRGBA_4444_GrPixelConfig];
260 if (this->isMac()) {
261 info->fFlags = 0;
262 } else {
263 info->fFlags = ConfigInfo::kAllFlags;
264 }
265
266 // RGBA_8888 uses RGBA8Unorm
267 info = &fConfigTable[kRGBA_8888_GrPixelConfig];
268 info->fFlags = ConfigInfo::kAllFlags;
269
270 // BGRA_8888 uses BGRA8Unorm
271 info = &fConfigTable[kBGRA_8888_GrPixelConfig];
272 info->fFlags = ConfigInfo::kAllFlags;
273
274 // SRGBA_8888 uses RGBA8Unorm_sRGB
275 info = &fConfigTable[kSRGBA_8888_GrPixelConfig];
276 info->fFlags = ConfigInfo::kAllFlags;
277
278 // SBGRA_8888 uses BGRA8Unorm_sRGB
279 info = &fConfigTable[kSBGRA_8888_GrPixelConfig];
280 info->fFlags = ConfigInfo::kAllFlags;
281
282 // RGBA_8888_sint uses RGBA8Sint
283 info = &fConfigTable[kRGBA_8888_sint_GrPixelConfig];
284 info->fFlags = ConfigInfo::kMSAA_Flag;
285
286 // RGBA_float uses RGBA32Float
287 info = &fConfigTable[kRGBA_float_GrPixelConfig];
288 if (this->isMac()) {
289 info->fFlags = ConfigInfo::kAllFlags;
290 } else {
291 info->fFlags = 0;
292 }
293
294 // RG_float uses RG32Float
295 info = &fConfigTable[kRG_float_GrPixelConfig];
296 if (this->isMac()) {
297 info->fFlags = ConfigInfo::kAllFlags;
298 } else {
299 info->fFlags = ConfigInfo::kRenderable_Flag;
300 }
301
302 // Alpha_half uses R16Float
303 info = &fConfigTable[kAlpha_half_GrPixelConfig];
304 info->fFlags = ConfigInfo::kAllFlags;
305
306 // RGBA_half uses RGBA16Float
307 info = &fConfigTable[kRGBA_half_GrPixelConfig];
308 info->fFlags = ConfigInfo::kAllFlags;
309}