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