Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
MtlCaps.mm
Go to the documentation of this file.
1/*
2 * Copyright 2021 Google LLC
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
13#include "src/gpu/SwizzlePriv.h"
23#include "src/sksl/SkSLUtil.h"
24
25namespace skgpu::graphite {
26
27MtlCaps::MtlCaps(const id<MTLDevice> device, const ContextOptions& options)
28 : Caps() {
29 this->initGPUFamily(device);
30 this->initCaps(device);
31 this->initShaderCaps();
32
33 this->initFormatTable();
34
35 // Metal-specific MtlCaps
36
37 this->finishInitialization(options);
38}
39
40// translates from older MTLFeatureSet interface to MTLGPUFamily interface
41bool MtlCaps::GetGPUFamilyFromFeatureSet(id<MTLDevice> device, GPUFamily* gpuFamily, int* group) {
42// MTLFeatureSet is deprecated for newer versions of the SDK
43#if SKGPU_GRAPHITE_METAL_SDK_VERSION < 300
44
45#if defined(SK_BUILD_FOR_MAC)
46 // Apple Silicon is only available in later OSes
47 *gpuFamily = GPUFamily::kMac;
48 // Mac OSX 14
49 if (@available(macOS 10.14, *)) {
50 if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily2_v1]) {
51 *group = 2;
52 return true;
53 }
54 if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v4]) {
55 *group = 1;
56 return true;
57 }
58 }
59 // Mac OSX 13
60 if (@available(macOS 10.13, *)) {
61 if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v3]) {
62 *group = 1;
63 return true;
64 }
65 }
66 // Mac OSX 12
67 if (@available(macOS 10.12, *)) {
68 if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v2]) {
69 *group = 1;
70 return true;
71 }
72 }
73 // Mac OSX 11
74 if (@available(macOS 10.11, *)) {
75 if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v1]) {
76 *group = 1;
77 return true;
78 }
79 }
80#elif defined(SK_BUILD_FOR_IOS)
81 // TODO: support tvOS
82 *gpuFamily = GPUFamily::kApple;
83 // iOS 12
84 if (@available(iOS 12.0, tvOS 12.0, *)) {
85 if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily5_v1]) {
86 *group = 5;
87 return true;
88 }
89 if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily4_v2]) {
90 *group = 4;
91 return true;
92 }
93 if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v4]) {
94 *group = 3;
95 return true;
96 }
97 if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily2_v5]) {
98 *group = 2;
99 return true;
100 }
101 if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily1_v5]) {
102 *group = 1;
103 return true;
104 }
105 }
106 // iOS 11
107 if (@available(iOS 11.0, tvOS 11.0, *)) {
108 if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily4_v1]) {
109 *group = 4;
110 return true;
111 }
112 if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v3]) {
113 *group = 3;
114 return true;
115 }
116 if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily2_v4]) {
117 *group = 2;
118 return true;
119 }
120 if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily1_v4]) {
121 *group = 1;
122 return true;
123 }
124 }
125 // iOS 10
126 if (@available(iOS 10.0, tvOS 10.0, *)) {
127 if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v2]) {
128 *group = 3;
129 return true;
130 }
131 if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily2_v3]) {
132 *group = 2;
133 return true;
134 }
135 if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily1_v3]) {
136 *group = 1;
137 return true;
138 }
139 }
140 // We don't support earlier OSes
141#endif
142
143#endif // SKGPU_GRAPHITE_METAL_SDK_VERSION < 300
144
145 // No supported GPU families were found
146 return false;
147}
148
149bool MtlCaps::GetGPUFamily(id<MTLDevice> device, GPUFamily* gpuFamily, int* group) {
150#if SKGPU_GRAPHITE_METAL_SDK_VERSION >= 220
151 if (@available(macOS 10.15, iOS 13.0, tvOS 13.0, *)) {
152 // Apple Silicon
153#if SKGPU_GRAPHITE_METAL_SDK_VERSION >= 230
154 if ([device supportsFamily:MTLGPUFamilyApple7]) {
155 *gpuFamily = GPUFamily::kApple;
156 *group = 7;
157 return true;
158 }
159#endif
160#ifdef SK_BUILD_FOR_IOS
161 if ([device supportsFamily:MTLGPUFamilyApple6]) {
162 *gpuFamily = GPUFamily::kApple;
163 *group = 6;
164 return true;
165 }
166 if ([device supportsFamily:MTLGPUFamilyApple5]) {
167 *gpuFamily = GPUFamily::kApple;
168 *group = 5;
169 return true;
170 }
171 if ([device supportsFamily:MTLGPUFamilyApple4]) {
172 *gpuFamily = GPUFamily::kApple;
173 *group = 4;
174 return true;
175 }
176 if ([device supportsFamily:MTLGPUFamilyApple3]) {
177 *gpuFamily = GPUFamily::kApple;
178 *group = 3;
179 return true;
180 }
181 if ([device supportsFamily:MTLGPUFamilyApple2]) {
182 *gpuFamily = GPUFamily::kApple;
183 *group = 2;
184 return true;
185 }
186 if ([device supportsFamily:MTLGPUFamilyApple1]) {
187 *gpuFamily = GPUFamily::kApple;
188 *group = 1;
189 return true;
190 }
191#endif
192
193 // Older Macs
194#if SKGPU_GRAPHITE_METAL_SDK_VERSION >= 300
195 // TODO: replace with Metal 3 definitions
196 SkASSERT([device supportsFamily:MTLGPUFamilyMac2]);
197 *gpuFamily = GPUFamily::kMac;
198 *group = 2;
199 return true;
200#else
201 // At the moment MacCatalyst families have the same features as Mac,
202 // so we treat them the same
203 if ([device supportsFamily:MTLGPUFamilyMac2] ||
204 [device supportsFamily:MTLGPUFamilyMacCatalyst2]) {
205 *gpuFamily = GPUFamily::kMac;
206 *group = 2;
207 return true;
208 }
209 if ([device supportsFamily:MTLGPUFamilyMac1] ||
210 [device supportsFamily:MTLGPUFamilyMacCatalyst1]) {
211 *gpuFamily = GPUFamily::kMac;
212 *group = 1;
213 return true;
214 }
215#endif
216 }
217#endif
218
219 // No supported GPU families were found
220 return false;
221}
222
223void MtlCaps::initGPUFamily(id<MTLDevice> device) {
224 if (@available(macOS 10.15, iOS 13.0, tvOS 13.0, *)) {
225 if (GetGPUFamily(device, &fGPUFamily, &fFamilyGroup)) {
226 return;
227 }
228 } else {
229 if (GetGPUFamilyFromFeatureSet(device, &fGPUFamily, &fFamilyGroup)) {
230 return;
231 }
232 }
233
234 // We don't know what this is, fall back to minimum defaults
235#ifdef SK_BUILD_FOR_MAC
236 fGPUFamily = GPUFamily::kMac;
237 fFamilyGroup = 1;
238#else
239 fGPUFamily = GPUFamily::kApple;
240 fFamilyGroup = 1;
241#endif
242}
243
244void MtlCaps::initCaps(const id<MTLDevice> device) {
245#if defined(GRAPHITE_TEST_UTILS)
246 this->setDeviceName([[device name] UTF8String]);
247#endif
248
249 if (this->isMac() || fFamilyGroup >= 3) {
250 fMaxTextureSize = 16384;
251 } else {
252 fMaxTextureSize = 8192;
253 }
254
255 // We use constant address space for our uniform buffers which has various alignment
256 // requirements for the offset when binding the buffer. On MacOS Intel the offset must align
257 // to 256. On iOS or Apple Silicon we must align to the max of the data type consumed by the
258 // vertex function or 4 bytes, or we can ignore the data type and just use 16 bytes.
259 //
260 // On Mac, all copies must be aligned to at least 4 bytes; on iOS there is no alignment.
261 if (this->isMac()) {
264 } else {
267 }
268
272
273 // Metal does not distinguish between uniform and storage buffers.
275
278
279 fComputeSupport = true;
280
281 if (@available(macOS 10.12, iOS 14.0, tvOS 14.0, *)) {
282 fClampToBorderSupport = (this->isMac() || fFamilyGroup >= 7);
283 } else {
284 fClampToBorderSupport = false;
285 }
286
287 // Init sample counts. All devices support 1 (i.e. 0 in skia).
288 fColorSampleCounts.push_back(1);
289 if (![device.name containsString:@"Intel"]) {
290 if (@available(macOS 10.11, iOS 9.0, tvOS 9.0, *)) {
291 for (auto sampleCnt : {2, 4, 8}) {
292 if ([device supportsTextureSampleCount:sampleCnt]) {
293 fColorSampleCounts.push_back(sampleCnt);
294 }
295 }
296 }
297 }
298}
299
300void MtlCaps::initShaderCaps() {
302
303 // Dual source blending requires Metal 1.2.
304 if (@available(macOS 10.12, iOS 10.0, tvOS 10.0, *)) {
306 }
307
308 // Setting this true with the assumption that this cap will eventually mean we support varying
309 // precisions and not just via modifiers.
312
315
316 if (@available(macOS 11.0, *)) {
317 if (this->isApple()) {
318 shaderCaps->fFBFetchSupport = true;
319 shaderCaps->fFBFetchColorName = "sk_LastFragColor";
320 }
321 }
322
326
327 // Metal uses IEEE floats so assuming those values here.
329}
330
331// Define this so we can use it to initialize arrays and work around
332// the fact that these pixel formats are not always available.
333#define kMTLPixelFormatB5G6R5Unorm MTLPixelFormat(40)
334#define kMTLPixelFormatABGR4Unorm MTLPixelFormat(42)
335#define kMTLPixelFormatETC2_RGB8 MTLPixelFormat(180)
336
337// These are all the valid MTLPixelFormats that we currently support in Skia. They are roughly
338// ordered from most frequently used to least to improve look up times in arrays.
339static constexpr MTLPixelFormat kMtlFormats[] = {
340 MTLPixelFormatRGBA8Unorm,
341 MTLPixelFormatR8Unorm,
342 MTLPixelFormatA8Unorm,
343 MTLPixelFormatBGRA8Unorm,
345 MTLPixelFormatRGBA16Float,
346 MTLPixelFormatR16Float,
347 MTLPixelFormatRG8Unorm,
348 MTLPixelFormatRGB10A2Unorm,
349 // MTLPixelFormatBGR10A2Unorm
351 MTLPixelFormatRGBA8Unorm_sRGB,
352 MTLPixelFormatR16Unorm,
353 MTLPixelFormatRG16Unorm,
355#ifdef SK_BUILD_FOR_MAC
356 MTLPixelFormatBC1_RGBA,
357#endif
358 MTLPixelFormatRGBA16Unorm,
359 MTLPixelFormatRG16Float,
360
361 MTLPixelFormatStencil8,
362 MTLPixelFormatDepth32Float,
363 MTLPixelFormatDepth32Float_Stencil8,
364
365 MTLPixelFormatInvalid,
366};
367
368void MtlCaps::setColorType(SkColorType colorType, std::initializer_list<MTLPixelFormat> formats) {
369 int idx = static_cast<int>(colorType);
370 for (auto it = formats.begin(); it != formats.end(); ++it) {
371 const auto& info = this->getFormatInfo(*it);
372 for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
373 if (info.fColorTypeInfos[i].fColorType == colorType) {
374 fColorTypeToFormatTable[idx] = *it;
375 return;
376 }
377 }
378 }
379}
380
381size_t MtlCaps::GetFormatIndex(MTLPixelFormat pixelFormat) {
382 static_assert(std::size(kMtlFormats) == MtlCaps::kNumMtlFormats,
383 "Size of kMtlFormats array must match static value in header");
384 for (size_t i = 0; i < MtlCaps::kNumMtlFormats; ++i) {
385 if (kMtlFormats[i] == pixelFormat) {
386 return i;
387 }
388 }
389 return GetFormatIndex(MTLPixelFormatInvalid);
390}
391
392void MtlCaps::initFormatTable() {
393 FormatInfo* info;
394
395 if (@available(macOS 11.0, iOS 8.0, tvOS 9.0, *)) {
396 if (this->isApple()) {
397 SkASSERT(kMTLPixelFormatB5G6R5Unorm == MTLPixelFormatB5G6R5Unorm);
398 SkASSERT(kMTLPixelFormatABGR4Unorm == MTLPixelFormatABGR4Unorm);
399 }
400 }
401
402 // Format: RGBA8Unorm
403 {
404 info = &fFormatTable[GetFormatIndex(MTLPixelFormatRGBA8Unorm)];
405 info->fFlags = FormatInfo::kAllFlags;
406 info->fColorTypeInfoCount = 2;
407 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
408 int ctIdx = 0;
409 // Format: RGBA8Unorm, Surface: kRGBA_8888
410 {
411 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
412 ctInfo.fColorType = kRGBA_8888_SkColorType;
413 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
414 }
415 // Format: RGBA8Unorm, Surface: kRGB_888x
416 {
417 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
418 ctInfo.fColorType = kRGB_888x_SkColorType;
419 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
420 ctInfo.fReadSwizzle = skgpu::Swizzle::RGB1();
421 }
422 }
423
424 // Format: R8Unorm
425 {
426 info = &fFormatTable[GetFormatIndex(MTLPixelFormatR8Unorm)];
427 info->fFlags = FormatInfo::kAllFlags;
428 info->fColorTypeInfoCount = 3;
429 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
430 int ctIdx = 0;
431 // Format: R8Unorm, Surface: kR8_unorm
432 {
433 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
434 ctInfo.fColorType = kR8_unorm_SkColorType;
435 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
436 }
437 // Format: R8Unorm, Surface: kAlpha_8
438 {
439 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
440 ctInfo.fColorType = kAlpha_8_SkColorType;
441 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
442 ctInfo.fReadSwizzle = skgpu::Swizzle("000r");
443 ctInfo.fWriteSwizzle = skgpu::Swizzle("a000");
444 }
445 // Format: R8Unorm, Surface: kGray_8
446 {
447 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
448 ctInfo.fColorType = kGray_8_SkColorType;
449 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
450 ctInfo.fReadSwizzle = skgpu::Swizzle("rrr1");
451 }
452 }
453
454 // Format: A8Unorm
455 {
456 info = &fFormatTable[GetFormatIndex(MTLPixelFormatA8Unorm)];
457 info->fFlags = FormatInfo::kTexturable_Flag;
458 info->fColorTypeInfoCount = 1;
459 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
460 int ctIdx = 0;
461 // Format: A8Unorm, Surface: kAlpha_8
462 {
463 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
464 ctInfo.fColorType = kAlpha_8_SkColorType;
465 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
466 }
467 }
468
469 // Format: BGRA8Unorm
470 {
471 info = &fFormatTable[GetFormatIndex(MTLPixelFormatBGRA8Unorm)];
472 info->fFlags = FormatInfo::kAllFlags;
473 info->fColorTypeInfoCount = 1;
474 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
475 int ctIdx = 0;
476 // Format: BGRA8Unorm, Surface: kBGRA_8888
477 {
478 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
479 ctInfo.fColorType = kBGRA_8888_SkColorType;
480 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
481 }
482 }
483
484 if (@available(macOS 11.0, iOS 8.0, tvOS 9.0, *)) {
485 if (this->isApple()) {
486 // Format: B5G6R5Unorm
487 {
488 info = &fFormatTable[GetFormatIndex(MTLPixelFormatB5G6R5Unorm)];
489 info->fFlags = FormatInfo::kAllFlags;
490 info->fColorTypeInfoCount = 1;
491 info->fColorTypeInfos =
492 std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
493 int ctIdx = 0;
494 // Format: B5G6R5Unorm, Surface: kBGR_565
495 {
496 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
497 ctInfo.fColorType = kRGB_565_SkColorType;
498 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag |
499 ColorTypeInfo::kRenderable_Flag;
500 }
501 }
502
503 // Format: ABGR4Unorm
504 {
505 info = &fFormatTable[GetFormatIndex(MTLPixelFormatABGR4Unorm)];
506 info->fFlags = FormatInfo::kAllFlags;
507 info->fColorTypeInfoCount = 1;
508 info->fColorTypeInfos =
509 std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
510 int ctIdx = 0;
511 // Format: ABGR4Unorm, Surface: kABGR_4444
512 {
513 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
514 ctInfo.fColorType = kARGB_4444_SkColorType;
515 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag |
516 ColorTypeInfo::kRenderable_Flag;
517 }
518 }
519 }
520 }
521
522 // Format: RGBA8Unorm_sRGB
523 {
524 info = &fFormatTable[GetFormatIndex(MTLPixelFormatRGBA8Unorm_sRGB)];
525 info->fFlags = FormatInfo::kAllFlags;
526 info->fColorTypeInfoCount = 1;
527 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
528 int ctIdx = 0;
529 // Format: RGBA8Unorm_sRGB, Surface: kSRGBA_8888
530 {
531 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
532 ctInfo.fColorType = kSRGBA_8888_SkColorType;
533 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
534 }
535 }
536
537 // Format: RGB10A2Unorm
538 {
539 info = &fFormatTable[GetFormatIndex(MTLPixelFormatRGB10A2Unorm)];
540 if (this->isMac() || fFamilyGroup >= 3) {
541 info->fFlags = FormatInfo::kAllFlags;
542 } else {
543 info->fFlags = FormatInfo::kTexturable_Flag;
544 }
545 info->fColorTypeInfoCount = 1;
546 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
547 int ctIdx = 0;
548 // Format: RGB10A2Unorm, Surface: kRGBA_1010102
549 {
550 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
551 ctInfo.fColorType = kRGBA_1010102_SkColorType;
552 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
553 }
554 }
555
556 // Format: RGBA16Float
557 {
558 info = &fFormatTable[GetFormatIndex(MTLPixelFormatRGBA16Float)];
559 info->fFlags = FormatInfo::kAllFlags;
560 info->fColorTypeInfoCount = 2;
561 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
562 int ctIdx = 0;
563 // Format: RGBA16Float, Surface: RGBA_F16
564 {
565 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
566 ctInfo.fColorType = kRGBA_F16_SkColorType;
567 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
568 }
569 // Format: RGBA16Float, Surface: RGBA_F16Norm
570 {
571 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
572 ctInfo.fColorType = kRGBA_F16Norm_SkColorType;
573 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
574 }
575 }
576
577 // Format: R16Float
578 {
579 info = &fFormatTable[GetFormatIndex(MTLPixelFormatR16Float)];
580 info->fFlags = FormatInfo::kAllFlags;
581 info->fColorTypeInfoCount = 1;
582 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
583 int ctIdx = 0;
584 // Format: R16Float, Surface: kA16_float
585 {
586 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
587 ctInfo.fColorType = kA16_float_SkColorType;
588 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
589 ctInfo.fReadSwizzle = skgpu::Swizzle("000r");
590 ctInfo.fWriteSwizzle = skgpu::Swizzle("a000");
591 }
592 }
593
594 // Format: RG8Unorm
595 {
596 info = &fFormatTable[GetFormatIndex(MTLPixelFormatRG8Unorm)];
597 info->fFlags = FormatInfo::kAllFlags;
598 info->fColorTypeInfoCount = 1;
599 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
600 int ctIdx = 0;
601 // Format: RG8Unorm, Surface: kR8G8_unorm
602 {
603 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
604 ctInfo.fColorType = kR8G8_unorm_SkColorType;
605 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
606 }
607 }
608
609 // Format: RGBA16Unorm
610 {
611 info = &fFormatTable[GetFormatIndex(MTLPixelFormatRGBA16Unorm)];
612 if (this->isMac()) {
613 info->fFlags = FormatInfo::kAllFlags;
614 } else {
615 info->fFlags = FormatInfo::kTexturable_Flag | FormatInfo::kRenderable_Flag;
616 }
617 info->fColorTypeInfoCount = 1;
618 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
619 int ctIdx = 0;
620 // Format: RGBA16Unorm, Surface: kR16G16B16A16_unorm
621 {
622 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
623 ctInfo.fColorType = kR16G16B16A16_unorm_SkColorType;
624 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
625 }
626 }
627
628 // Format: RG16Float
629 {
630 info = &fFormatTable[GetFormatIndex(MTLPixelFormatRG16Float)];
631 info->fFlags = FormatInfo::kAllFlags;
632 info->fColorTypeInfoCount = 1;
633 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
634 int ctIdx = 0;
635 // Format: RG16Float, Surface: kR16G16_float
636 {
637 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
638 ctInfo.fColorType = kR16G16_float_SkColorType;
639 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
640 }
641 }
642
643 // Format: R16Unorm
644 {
645 info = &fFormatTable[GetFormatIndex(MTLPixelFormatR16Unorm)];
646 if (this->isMac()) {
647 info->fFlags = FormatInfo::kAllFlags;
648 } else {
649 info->fFlags = FormatInfo::kTexturable_Flag | FormatInfo::kRenderable_Flag;
650 }
651 info->fColorTypeInfoCount = 1;
652 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
653 int ctIdx = 0;
654 // Format: R16Unorm, Surface: kA16_unorm
655 {
656 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
657 ctInfo.fColorType = kA16_unorm_SkColorType;
658 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
659 ctInfo.fReadSwizzle = skgpu::Swizzle("000r");
660 ctInfo.fWriteSwizzle = skgpu::Swizzle("a000");
661 }
662 }
663
664 // Format: RG16Unorm
665 {
666 info = &fFormatTable[GetFormatIndex(MTLPixelFormatRG16Unorm)];
667 if (this->isMac()) {
668 info->fFlags = FormatInfo::kAllFlags;
669 } else {
670 info->fFlags = FormatInfo::kTexturable_Flag | FormatInfo::kRenderable_Flag;
671 }
672 info->fColorTypeInfoCount = 1;
673 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
674 int ctIdx = 0;
675 // Format: RG16Unorm, Surface: kR16G16_unorm
676 {
677 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
678 ctInfo.fColorType = kR16G16_unorm_SkColorType;
679 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
680 }
681 }
682
683 // Format: ETC2_RGB8
684 {
685 if (@available(macOS 11.0, iOS 8.0, tvOS 9.0, *)) {
686 if (this->isApple()) {
687 info = &fFormatTable[GetFormatIndex(MTLPixelFormatETC2_RGB8)];
688 info->fFlags = FormatInfo::kTexturable_Flag;
689 info->fColorTypeInfoCount = 1;
690 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
691 int ctIdx = 0;
692 // Format: ETC2_RGB8, Surface: kRGB_888x
693 {
694 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
695 ctInfo.fColorType = kRGB_888x_SkColorType;
696 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
697 }
698 }
699 }
700 }
701
702 // Format: BC1_RGBA
703 {
704#ifdef SK_BUILD_FOR_MAC
705 if (this->isMac()) {
706 info = &fFormatTable[GetFormatIndex(MTLPixelFormatBC1_RGBA)];
707 info->fFlags = FormatInfo::kTexturable_Flag;
708 info->fColorTypeInfoCount = 1;
709 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
710 int ctIdx = 0;
711 // Format: BC1_RGBA, Surface: kRGBA_8888
712 {
713 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
714 ctInfo.fColorType = kRGBA_8888_SkColorType;
715 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
716 }
717 }
718#endif
719 }
720
721 /*
722 * Non-color formats
723 */
724
725 // Format: Stencil8
726 {
727 info = &fFormatTable[GetFormatIndex(MTLPixelFormatStencil8)];
728 info->fFlags = FormatInfo::kMSAA_Flag;
729 info->fColorTypeInfoCount = 0;
730 }
731
732 // Format: Depth32Float
733 {
734 info = &fFormatTable[GetFormatIndex(MTLPixelFormatDepth32Float)];
735 info->fFlags = FormatInfo::kMSAA_Flag;
736 if (this->isMac() || fFamilyGroup >= 3) {
737 info->fFlags |= FormatInfo::kResolve_Flag;
738 }
739 info->fColorTypeInfoCount = 0;
740 }
741
742 // Format: Depth32Float_Stencil8
743 {
744 info = &fFormatTable[GetFormatIndex(MTLPixelFormatDepth32Float_Stencil8)];
745 info->fFlags = FormatInfo::kMSAA_Flag;
746 if (this->isMac() || fFamilyGroup >= 3) {
747 info->fFlags |= FormatInfo::kResolve_Flag;
748 }
749 info->fColorTypeInfoCount = 0;
750 }
751
752 ////////////////////////////////////////////////////////////////////////////
753 // Map SkColorTypes (used for creating SkSurfaces) to MTLPixelFormats. The order in which the
754 // formats are passed into the setColorType function indicates the priority in selecting which
755 // format we use for a given SkColorType.
756
757 std::fill_n(fColorTypeToFormatTable, kSkColorTypeCnt, MTLPixelFormatInvalid);
758
759 this->setColorType(kAlpha_8_SkColorType, { MTLPixelFormatR8Unorm,
760 MTLPixelFormatA8Unorm });
761 if (@available(macOS 11.0, iOS 8.0, tvOS 9.0, *)) {
762 if (this->isApple()) {
763 this->setColorType(kRGB_565_SkColorType, {MTLPixelFormatB5G6R5Unorm});
764 this->setColorType(kARGB_4444_SkColorType, { MTLPixelFormatABGR4Unorm });
765 }
766 }
767
768 this->setColorType(kRGBA_8888_SkColorType, { MTLPixelFormatRGBA8Unorm });
769 this->setColorType(kRGB_888x_SkColorType, { MTLPixelFormatRGBA8Unorm });
770 this->setColorType(kBGRA_8888_SkColorType, { MTLPixelFormatBGRA8Unorm });
771 this->setColorType(kRGBA_1010102_SkColorType, { MTLPixelFormatRGB10A2Unorm });
772 // kBGRA_1010102_SkColorType
773 // kRGB_101010x_SkColorType
774 // kBGR_101010x_SkColorType
775 // kBGR_101010x_XR_SkColorType
776 this->setColorType(kGray_8_SkColorType, { MTLPixelFormatR8Unorm });
777 this->setColorType(kRGBA_F16Norm_SkColorType, { MTLPixelFormatRGBA16Float });
778 this->setColorType(kRGBA_F16_SkColorType, { MTLPixelFormatRGBA16Float });
779 // kRGBA_F32_SkColorType
780 this->setColorType(kR8G8_unorm_SkColorType, { MTLPixelFormatRG8Unorm });
781 this->setColorType(kA16_float_SkColorType, { MTLPixelFormatR16Float });
782 this->setColorType(kR16G16_float_SkColorType, { MTLPixelFormatRG16Float });
783 this->setColorType(kA16_unorm_SkColorType, { MTLPixelFormatR16Unorm });
784 this->setColorType(kR16G16_unorm_SkColorType, { MTLPixelFormatRG16Unorm });
785 this->setColorType(kR16G16B16A16_unorm_SkColorType,{ MTLPixelFormatRGBA16Unorm });
786 this->setColorType(kSRGBA_8888_SkColorType, { MTLPixelFormatRGBA8Unorm_sRGB });
787 this->setColorType(kR8_unorm_SkColorType, { MTLPixelFormatR8Unorm });
788
789}
790
792 Mipmapped mipmapped,
793 Protected,
794 Renderable renderable) const {
795 MTLTextureUsage usage = MTLTextureUsageShaderRead;
796 if (renderable == Renderable::kYes) {
797 usage |= MTLTextureUsageRenderTarget;
798 }
799
800 MtlPixelFormat format = this->getFormatFromColorType(colorType);
801 if (format == MTLPixelFormatInvalid) {
802 return {};
803 }
804
806 info.fSampleCount = 1;
807 info.fMipmapped = mipmapped;
808 info.fFormat = format;
809 info.fUsage = usage;
810 info.fStorageMode = MTLStorageModePrivate;
811 info.fFramebufferOnly = false;
812
813 return info;
814}
815
817 Mipmapped mipmapped) const {
819 if (!textureInfo.getMtlTextureInfo(&info)) {
820 return {};
821 }
822
823 info.fSampleCount = 1;
824 info.fMipmapped = mipmapped;
825 info.fUsage = MTLTextureUsageShaderRead;
826 info.fStorageMode = MTLStorageModePrivate;
827 info.fFramebufferOnly = false;
828
829 return info;
830}
831
832namespace {
833MTLPixelFormat format_from_compression(SkTextureCompressionType compression) {
834 switch (compression) {
838#ifdef SK_BUILD_FOR_MAC
839 return MTLPixelFormatBC1_RGBA;
840#endif
841 default:
842 return MTLPixelFormatInvalid;
843 }
844}
845}
846
848 Mipmapped mipmapped,
849 Protected) const {
850 MTLTextureUsage usage = MTLTextureUsageShaderRead;
851
852 MtlPixelFormat format = format_from_compression(compression);
853 if (format == MTLPixelFormatInvalid) {
854 return {};
855 }
856
858 info.fSampleCount = 1;
859 info.fMipmapped = mipmapped;
860 info.fFormat = format;
861 info.fUsage = usage;
862 info.fStorageMode = MTLStorageModePrivate;
863 info.fFramebufferOnly = false;
864
865 return info;
866}
867
868MTLStorageMode MtlCaps::getDefaultMSAAStorageMode(Discardable discardable) const {
869 // Try to use memoryless if it's available (only on new Apple silicon)
870 if (discardable == Discardable::kYes && this->isApple()) {
871 if (@available(macOS 11.0, iOS 10.0, tvOS 10.0, *)) {
872 return MTLStorageModeMemoryless;
873 }
874 }
875 // If it's not discardable or not available, private is the best option
876 return MTLStorageModePrivate;
877}
878
880 Discardable discardable) const {
881 if (fDefaultMSAASamples <= 1) {
882 return {};
883 }
884 const MtlTextureSpec& singleSpec = singleSampledInfo.mtlTextureSpec();
885 if (!this->isRenderable((MTLPixelFormat)singleSpec.fFormat, fDefaultMSAASamples)) {
886 return {};
887 }
888
889 MTLTextureUsage usage = MTLTextureUsageRenderTarget;
890
893 info.fMipmapped = Mipmapped::kNo;
894 info.fFormat = singleSpec.fFormat;
895 info.fUsage = usage;
896 info.fStorageMode = this->getDefaultMSAAStorageMode(discardable);
897 info.fFramebufferOnly = false;
898
899 return info;
900}
901
903 SkEnumBitMask<DepthStencilFlags> depthStencilType,
904 uint32_t sampleCount,
905 Protected) const {
907 info.fSampleCount = sampleCount;
908 info.fMipmapped = Mipmapped::kNo;
909 info.fFormat = MtlDepthStencilFlagsToFormat(depthStencilType);
910 info.fUsage = MTLTextureUsageRenderTarget;
911 info.fStorageMode = this->getDefaultMSAAStorageMode(Discardable::kYes);
912 info.fFramebufferOnly = false;
913
914 return info;
915}
916
918 // Storage textures are currently always sampleable from a shader.
919 MTLPixelFormat format = static_cast<MTLPixelFormat>(this->getFormatFromColorType(colorType));
920 if (format == MTLPixelFormatInvalid) {
921 return {};
922 }
923
924 const FormatInfo& formatInfo = this->getFormatInfo(format);
925 if (!SkToBool(FormatInfo::kStorage_Flag & formatInfo.fFlags)) {
926 return {};
927 }
928
929 MTLTextureUsage usage = MTLTextureUsageShaderWrite | MTLTextureUsageShaderRead;
931 info.fSampleCount = 1;
932 info.fMipmapped = Mipmapped::kNo;
933 info.fFormat = format;
934 info.fUsage = usage;
935 info.fStorageMode = MTLStorageModePrivate;
936 info.fFramebufferOnly = false;
937
938 return info;
939}
940
942 SkColorType ct, const TextureInfo& textureInfo) const {
943 MTLPixelFormat mtlFormat = static_cast<MTLPixelFormat>(textureInfo.mtlTextureSpec().fFormat);
944 if (mtlFormat == MTLPixelFormatInvalid) {
945 return nullptr;
946 }
947
948 const FormatInfo& info = this->getFormatInfo(mtlFormat);
949 for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
950 const ColorTypeInfo& ctInfo = info.fColorTypeInfos[i];
951 if (ctInfo.fColorType == ct) {
952 return &ctInfo;
953 }
954 }
955
956 return nullptr;
957}
958
961
963 const RenderPassDesc& renderPassDesc) const {
964 UniqueKey pipelineKey;
965 {
966 // 5 uint32_t's (render step id, paint id, uint64 renderpass desc, uint16 write swizzle key)
967 UniqueKey::Builder builder(&pipelineKey, kGraphicsPipelineDomain,
968 kGraphicsPipelineKeyData32Count, "GraphicsPipeline");
969 // add GraphicsPipelineDesc key
970 builder[0] = pipelineDesc.renderStepID();
971 builder[1] = pipelineDesc.paintParamsID().asUInt();
972
973 // add RenderPassDesc key
974 uint64_t renderPassKey = this->getRenderPassDescKey(renderPassDesc);
975 builder[2] = renderPassKey & 0xFFFFFFFF;
976 builder[3] = (renderPassKey >> 32) & 0xFFFFFFFF;
977 builder[4] = renderPassDesc.fWriteSwizzle.asKey();
978
979 builder.finish();
980 }
981
982 return pipelineKey;
983}
984
986 GraphicsPipelineDesc* pipelineDesc,
987 RenderPassDesc* renderPassDesc,
988 const RendererProvider* rendererProvider) const {
989 struct UnpackedKeyData {
990 // From the GraphicsPipelineDesc
991 uint32_t fRenderStepID = 0;
992 UniquePaintParamsID fPaintParamsID;
993
994 // From the RenderPassDesc
995 MtlPixelFormat fColorFormat = 0;
996 uint32_t fColorSampleCount = 1;
997
998 MtlPixelFormat fDSFormat = 0;
999 uint32_t fDSSampleCount = 1;
1000
1001 Swizzle fWriteSwizzle;
1002 } keyData;
1003
1005 SkASSERT(key.dataSize() == 4 * kGraphicsPipelineKeyData32Count);
1006
1007 const uint32_t* rawKeyData = key.data();
1008
1009 keyData.fRenderStepID = rawKeyData[0];
1010 keyData.fPaintParamsID = rawKeyData[1] ? UniquePaintParamsID(rawKeyData[1])
1012
1013 keyData.fDSFormat = static_cast<MtlPixelFormat>((rawKeyData[2] >> 16) & 0xFFFF);
1014 keyData.fDSSampleCount = rawKeyData[2] & 0xFFFF;
1015
1016 keyData.fColorFormat = static_cast<MtlPixelFormat>((rawKeyData[3] >> 16) & 0xFFFF);
1017 keyData.fColorSampleCount = rawKeyData[3] & 0xFFFF;
1018
1019 keyData.fWriteSwizzle = SwizzleCtorAccessor::Make(rawKeyData[4]);
1020
1021 // Recreate the RenderPassDesc
1022 SkASSERT(keyData.fColorSampleCount == keyData.fDSSampleCount);
1023
1025 MtlFormatToDepthStencilFlags((MTLPixelFormat) keyData.fDSFormat);
1026
1027 MtlTextureInfo mtlInfo(keyData.fColorSampleCount,
1028 skgpu::Mipmapped::kNo,
1029 keyData.fColorFormat,
1030 MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget,
1031 MTLStorageModePrivate,
1032 /* framebufferOnly= */ false);
1033 TextureInfo info(mtlInfo);
1034
1035 *renderPassDesc = RenderPassDesc::Make(this,
1036 info,
1039 dsFlags,
1040 /* clearColor= */ { .0f, .0f, .0f, .0f },
1041 /* requiresMSAA= */ keyData.fColorSampleCount > 1,
1042 keyData.fWriteSwizzle);
1043
1044 // Recreate the GraphicsPipelineDesc
1045 const RenderStep* renderStep = rendererProvider->lookup(keyData.fRenderStepID);
1046
1047 UniquePaintParamsID paintID = renderStep->performsShading() ? keyData.fPaintParamsID
1049
1050 *pipelineDesc = GraphicsPipelineDesc(renderStep, paintID);
1051
1052 return true;
1053}
1054
1055uint64_t MtlCaps::getRenderPassDescKey(const RenderPassDesc& renderPassDesc) const {
1056 MtlTextureInfo colorInfo, depthStencilInfo;
1057 renderPassDesc.fColorAttachment.fTextureInfo.getMtlTextureInfo(&colorInfo);
1058 renderPassDesc.fDepthStencilAttachment.fTextureInfo.getMtlTextureInfo(&depthStencilInfo);
1059 SkASSERT(colorInfo.fFormat < 65535 && depthStencilInfo.fFormat < 65535);
1060 uint32_t colorAttachmentKey = colorInfo.fFormat << 16 | colorInfo.fSampleCount;
1061 uint32_t dsAttachmentKey = depthStencilInfo.fFormat << 16 | depthStencilInfo.fSampleCount;
1062 return (((uint64_t) colorAttachmentKey) << 32) | dsAttachmentKey;
1063}
1064
1066 UniqueKey pipelineKey;
1067 {
1068 static const skgpu::UniqueKey::Domain kComputePipelineDomain = UniqueKey::GenerateDomain();
1069 // The key is made up of a single uint32_t corresponding to the compute step ID.
1070 UniqueKey::Builder builder(&pipelineKey, kComputePipelineDomain, 1, "ComputePipeline");
1071 builder[0] = pipelineDesc.computeStep()->uniqueID();
1072
1073 // TODO(b/240615224): The local work group size should factor into the key on platforms
1074 // that don't support specialization constants and require the workgroup/threadgroup size to
1075 // be specified in the shader text (D3D12, Vulkan 1.0, and OpenGL).
1076
1077 builder.finish();
1078 }
1079 return pipelineKey;
1080}
1081
1082uint32_t MtlCaps::channelMask(const TextureInfo& info) const {
1083 return skgpu::MtlFormatChannels((MTLPixelFormat)info.mtlTextureSpec().fFormat);
1084}
1085
1087 if (!info.isValid()) {
1088 return false;
1089 }
1090 if (!(info.mtlTextureSpec().fUsage & MTLTextureUsageShaderRead)) {
1091 return false;
1092 }
1093 if (info.mtlTextureSpec().fFramebufferOnly) {
1094 return false;
1095 }
1096 return this->isTexturable((MTLPixelFormat)info.mtlTextureSpec().fFormat);
1097}
1098
1099bool MtlCaps::isTexturable(MTLPixelFormat format) const {
1100 const FormatInfo& formatInfo = this->getFormatInfo(format);
1101 return SkToBool(FormatInfo::kTexturable_Flag & formatInfo.fFlags);
1102}
1103
1105 return info.isValid() &&
1106 (info.mtlTextureSpec().fUsage & MTLTextureUsageRenderTarget) &&
1107 this->isRenderable((MTLPixelFormat)info.mtlTextureSpec().fFormat, info.numSamples());
1108}
1109
1110bool MtlCaps::isRenderable(MTLPixelFormat format, uint32_t sampleCount) const {
1111 return sampleCount <= this->maxRenderTargetSampleCount(format);
1112}
1113
1115 if (!info.isValid()) {
1116 return false;
1117 }
1118 if (!(info.mtlTextureSpec().fUsage & MTLTextureUsageShaderWrite)) {
1119 return false;
1120 }
1121 if (info.mtlTextureSpec().fFramebufferOnly) {
1122 return false;
1123 }
1124 const FormatInfo& formatInfo =
1125 this->getFormatInfo((MTLPixelFormat)info.mtlTextureSpec().fFormat);
1126 return info.numSamples() == 1 && SkToBool(FormatInfo::kStorage_Flag & formatInfo.fFlags);
1127}
1128
1129uint32_t MtlCaps::maxRenderTargetSampleCount(MTLPixelFormat format) const {
1130 const FormatInfo& formatInfo = this->getFormatInfo(format);
1131 if (!SkToBool(formatInfo.fFlags & FormatInfo::kRenderable_Flag)) {
1132 return 0;
1133 }
1134 if (SkToBool(formatInfo.fFlags & FormatInfo::kMSAA_Flag)) {
1135 return fColorSampleCounts[fColorSampleCounts.size() - 1];
1136 } else {
1137 return 1;
1138 }
1139}
1140
1141bool MtlCaps::supportsWritePixels(const TextureInfo& texInfo) const {
1142 MtlTextureInfo mtlInfo;
1143 texInfo.getMtlTextureInfo(&mtlInfo);
1144 if (mtlInfo.fFramebufferOnly) {
1145 return false;
1146 }
1147
1148 if (texInfo.numSamples() > 1) {
1149 return false;
1150 }
1151
1152 return true;
1153}
1154
1155bool MtlCaps::supportsReadPixels(const TextureInfo& texInfo) const {
1156 MtlTextureInfo mtlInfo;
1157 texInfo.getMtlTextureInfo(&mtlInfo);
1158 if (mtlInfo.fFramebufferOnly) {
1159 return false;
1160 }
1161
1162 // We disallow reading back directly from compressed textures.
1163 if (MtlFormatIsCompressed((MTLPixelFormat)mtlInfo.fFormat)) {
1164 return false;
1165 }
1166
1167 if (texInfo.numSamples() > 1) {
1168 return false;
1169 }
1170
1171 return true;
1172}
1173
1175 SkColorType dstColorType,
1176 const TextureInfo& dstTextureInfo,
1177 SkColorType srcColorType) const {
1178 MtlTextureInfo mtlInfo;
1179 dstTextureInfo.getMtlTextureInfo(&mtlInfo);
1180
1181 const FormatInfo& info = this->getFormatInfo((MTLPixelFormat)mtlInfo.fFormat);
1182 for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1183 const auto& ctInfo = info.fColorTypeInfos[i];
1184 if (ctInfo.fColorType == dstColorType) {
1185 return {dstColorType, false};
1186 }
1187 }
1188 return {kUnknown_SkColorType, false};
1189}
1190
1192 SkColorType srcColorType,
1193 const TextureInfo& srcTextureInfo,
1194 SkColorType dstColorType) const {
1195 MtlTextureInfo mtlInfo;
1196 srcTextureInfo.getMtlTextureInfo(&mtlInfo);
1197
1198 // TODO: handle compressed formats
1199 if (MtlFormatIsCompressed((MTLPixelFormat)mtlInfo.fFormat)) {
1200 SkASSERT(this->isTexturable((MTLPixelFormat)mtlInfo.fFormat));
1201 return {kUnknown_SkColorType, false};
1202 }
1203
1204 const FormatInfo& info = this->getFormatInfo((MTLPixelFormat)mtlInfo.fFormat);
1205 for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
1206 const auto& ctInfo = info.fColorTypeInfos[i];
1207 if (ctInfo.fColorType == srcColorType) {
1208 return {srcColorType, false};
1209 }
1210 }
1211 return {kUnknown_SkColorType, false};
1212}
1213
1215 const TextureInfo& info,
1217 Shareable shareable,
1218 GraphiteResourceKey* key) const {
1219 const MtlTextureSpec& mtlSpec = info.mtlTextureSpec();
1220
1221 SkASSERT(!dimensions.isEmpty());
1222
1223 // A MTLPixelFormat is an NSUInteger type which is documented to be 32 bits in 32 bit
1224 // applications and 64 bits in 64 bit applications. So it should fit in an uint64_t, but adding
1225 // the assert heere to make sure.
1226 static_assert(sizeof(MTLPixelFormat) <= sizeof(uint64_t));
1227 SkASSERT(mtlSpec.fFormat != MTLPixelFormatInvalid);
1228 uint64_t formatKey = static_cast<uint64_t>(mtlSpec.fFormat);
1229
1230 uint32_t samplesKey = SamplesToKey(info.numSamples());
1231 // We don't have to key the number of mip levels because it is inherit in the combination of
1232 // isMipped and dimensions.
1233 bool isMipped = info.mipmapped() == Mipmapped::kYes;
1234 Protected isProtected = info.isProtected();
1235 bool isFBOnly = mtlSpec.fFramebufferOnly;
1236
1237 // Confirm all the below parts of the key can fit in a single uint32_t. The sum of the shift
1238 // amounts in the asserts must be less than or equal to 32.
1239 SkASSERT(samplesKey < (1u << 3));
1240 SkASSERT(static_cast<uint32_t>(isMipped) < (1u << 1));
1241 SkASSERT(static_cast<uint32_t>(isProtected) < (1u << 1));
1242 SkASSERT(mtlSpec.fUsage < (1u << 5));
1243 SkASSERT(mtlSpec.fStorageMode < (1u << 2));
1244 SkASSERT(static_cast<uint32_t>(isFBOnly) < (1u << 1));
1245
1246 // We need two uint32_ts for dimensions, 2 for format, and 1 for the rest of the key;
1247 static int kNum32DataCnt = 2 + 2 + 1;
1248
1249 GraphiteResourceKey::Builder builder(key, type, kNum32DataCnt, shareable);
1250
1251 builder[0] = dimensions.width();
1252 builder[1] = dimensions.height();
1253 builder[2] = formatKey & 0xFFFFFFFF;
1254 builder[3] = (formatKey >> 32) & 0xFFFFFFFF;
1255 builder[4] = (samplesKey << 0) |
1256 (static_cast<uint32_t>(isMipped) << 3) |
1257 (static_cast<uint32_t>(isProtected) << 4) |
1258 (static_cast<uint32_t>(mtlSpec.fUsage) << 5) |
1259 (static_cast<uint32_t>(mtlSpec.fStorageMode) << 10)|
1260 (static_cast<uint32_t>(isFBOnly) << 12);
1261
1262}
1263
1264} // namespace skgpu::graphite
const char * options
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
#define kMTLPixelFormatB5G6R5Unorm
Definition GrMtlCaps.mm:586
#define kMTLPixelFormatETC2_RGB8
Definition GrMtlCaps.mm:588
#define kMTLPixelFormatABGR4Unorm
Definition GrMtlCaps.mm:587
#define SkASSERT(cond)
Definition SkAssert.h:116
SkColorType
Definition SkColorType.h:19
@ kR16G16B16A16_unorm_SkColorType
pixel with a little endian uint16_t for red, green, blue
Definition SkColorType.h:50
@ kR8_unorm_SkColorType
Definition SkColorType.h:54
@ kARGB_4444_SkColorType
pixel with 4 bits for alpha, red, green, blue; in 16-bit word
Definition SkColorType.h:23
@ kR8G8_unorm_SkColorType
pixel with a uint8_t for red and green
Definition SkColorType.h:43
@ kBGRA_8888_SkColorType
pixel with 8 bits for blue, green, red, alpha; in 32-bit word
Definition SkColorType.h:26
@ kA16_unorm_SkColorType
pixel with a little endian uint16_t for alpha
Definition SkColorType.h:48
@ kRGBA_F16_SkColorType
pixel with half floats for red, green, blue, alpha;
Definition SkColorType.h:38
@ kAlpha_8_SkColorType
pixel with alpha in 8-bit byte
Definition SkColorType.h:21
@ kSRGBA_8888_SkColorType
Definition SkColorType.h:53
@ kGray_8_SkColorType
pixel with grayscale level in 8-bit byte
Definition SkColorType.h:35
@ kRGB_565_SkColorType
pixel with 5 bits red, 6 bits green, 5 bits blue, in 16-bit word
Definition SkColorType.h:22
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition SkColorType.h:24
@ kRGB_888x_SkColorType
pixel with 8 bits each for red, green, blue; in 32-bit word
Definition SkColorType.h:25
@ kA16_float_SkColorType
pixel with a half float for alpha
Definition SkColorType.h:45
@ kRGBA_1010102_SkColorType
10 bits for red, green, blue; 2 bits for alpha; in 32-bit word
Definition SkColorType.h:27
@ kR16G16_unorm_SkColorType
pixel with a little endian uint16_t for red and green
Definition SkColorType.h:49
@ kRGBA_F16Norm_SkColorType
pixel with half floats in [0,1] for red, green, blue, alpha;
Definition SkColorType.h:36
@ kUnknown_SkColorType
uninitialized
Definition SkColorType.h:20
@ kR16G16_float_SkColorType
pixel with a half float for red and green
Definition SkColorType.h:46
static constexpr int kSkColorTypeCnt
Definition SkColorType.h:68
static SkColorType colorType(AImageDecoder *decoder, const AImageDecoderHeaderInfo *headerInfo)
static constexpr bool SkToBool(const T &x)
Definition SkTo.h:35
static Swizzle Make(uint16_t key)
Definition SwizzlePriv.h:21
constexpr uint16_t asKey() const
Definition Swizzle.h:43
static constexpr Swizzle RGB1()
Definition Swizzle.h:69
static Domain GenerateDomain()
size_t fRequiredStorageBufferAlignment
Definition Caps.h:342
size_t fRequiredUniformBufferAlignment
Definition Caps.h:341
bool fStorageBufferPreferred
Definition Caps.h:353
bool fClampToBorderSupport
Definition Caps.h:348
std::unique_ptr< SkSL::ShaderCaps > fShaderCaps
Definition Caps.h:346
bool fStorageBufferSupport
Definition Caps.h:352
static uint32_t SamplesToKey(uint32_t numSamples)
Definition Caps.h:305
void finishInitialization(const ContextOptions &)
Definition Caps.cpp:29
size_t fRequiredTransferBufferAlignment
Definition Caps.h:343
const SkSL::ShaderCaps * shaderCaps() const
Definition Caps.h:74
ResourceBindingRequirements fResourceBindingReqs
Definition Caps.h:366
const ComputeStep * computeStep() const
UniquePaintParamsID paintParamsID() const
void buildKeyForTexture(SkISize dimensions, const TextureInfo &, ResourceType, Shareable, GraphiteResourceKey *) const override
Definition MtlCaps.mm:1214
TextureInfo getDefaultMSAATextureInfo(const TextureInfo &singleSampledInfo, Discardable discardable) const override
Definition MtlCaps.mm:879
TextureInfo getTextureInfoForSampledCopy(const TextureInfo &textureInfo, Mipmapped mipmapped) const override
Definition MtlCaps.mm:816
TextureInfo getDefaultCompressedTextureInfo(SkTextureCompressionType, Mipmapped mipmapped, Protected) const override
Definition MtlCaps.mm:847
std::pair< SkColorType, bool > supportedWritePixelsColorType(SkColorType dstColorType, const TextureInfo &dstTextureInfo, SkColorType srcColorType) const override
Definition MtlCaps.mm:1174
bool extractGraphicsDescs(const UniqueKey &, GraphicsPipelineDesc *, RenderPassDesc *, const RendererProvider *) const override
Definition MtlCaps.mm:985
bool isStorage(const TextureInfo &) const override
Definition MtlCaps.mm:1114
bool supportsReadPixels(const TextureInfo &) const override
Definition MtlCaps.mm:1155
TextureInfo getDefaultSampledTextureInfo(SkColorType, Mipmapped mipmapped, Protected, Renderable) const override
Definition MtlCaps.mm:791
bool onIsTexturable(const TextureInfo &) const override
Definition MtlCaps.mm:1086
MtlCaps(const id< MTLDevice >, const ContextOptions &)
Definition MtlCaps.mm:27
bool supportsWritePixels(const TextureInfo &) const override
Definition MtlCaps.mm:1141
bool isApple() const
Definition MtlCaps.h:60
TextureInfo getDefaultDepthStencilTextureInfo(SkEnumBitMask< DepthStencilFlags >, uint32_t sampleCount, Protected) const override
Definition MtlCaps.mm:902
std::pair< SkColorType, bool > supportedReadPixelsColorType(SkColorType srcColorType, const TextureInfo &srcTextureInfo, SkColorType dstColorType) const override
Definition MtlCaps.mm:1191
bool isMac() const
Definition MtlCaps.h:59
TextureInfo getDefaultStorageTextureInfo(SkColorType) const override
Definition MtlCaps.mm:917
UniqueKey makeComputePipelineKey(const ComputePipelineDesc &) const override
Definition MtlCaps.mm:1065
uint64_t getRenderPassDescKey(const RenderPassDesc &) const
Definition MtlCaps.mm:1055
bool isRenderable(const TextureInfo &) const override
Definition MtlCaps.mm:1104
uint32_t channelMask(const TextureInfo &) const override
Definition MtlCaps.mm:1082
UniqueKey makeGraphicsPipelineKey(const GraphicsPipelineDesc &, const RenderPassDesc &) const override
Definition MtlCaps.mm:962
const ColorTypeInfo * getColorTypeInfo(SkColorType, const TextureInfo &) const override
Definition MtlCaps.mm:941
const RenderStep * lookup(uint32_t uniqueID) const
uint32_t numSamples() const
Definition TextureInfo.h:78
static UniquePaintParamsID InvalidID()
VkDevice device
Definition main.cc:53
uint32_t uint32_t * format
const char * name
Definition fuchsia.cc:50
unsigned int MtlPixelFormat
SkEnumBitMask< DepthStencilFlags > MtlFormatToDepthStencilFlags(MTLPixelFormat format)
uint32_t ResourceType
MTLPixelFormat MtlDepthStencilFlagsToFormat(SkEnumBitMask< DepthStencilFlags > mask)
static const int kGraphicsPipelineKeyData32Count
Definition MtlCaps.mm:960
static constexpr MTLPixelFormat kMtlFormats[]
Definition MtlCaps.mm:339
static const skgpu::UniqueKey::Domain kGraphicsPipelineDomain
Definition MtlCaps.mm:959
uint32_t MtlFormatChannels(MTLPixelFormat mtlFormat)
Definition MtlUtils.mm:91
Renderable
Definition GpuTypes.h:69
Mipmapped
Definition GpuTypes.h:53
bool MtlFormatIsCompressed(MTLPixelFormat mtlFormat)
Definition MtlUtils.mm:49
Protected
Definition GpuTypes.h:61
static void usage(char *argv0)
bool isEmpty() const
Definition SkSize.h:31
constexpr int32_t width() const
Definition SkSize.h:36
constexpr int32_t height() const
Definition SkSize.h:37
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
static RenderPassDesc Make(const Caps *caps, const TextureInfo &targetInfo, LoadOp loadOp, StoreOp storeOp, SkEnumBitMask< DepthStencilFlags > depthStencilFlags, const std::array< float, 4 > &clearColor, bool requiresMSAA, Swizzle writeSwizzle)